Skip to content

Commit 2377a85

Browse files
committed
Add tests for unix_socket server processes
1 parent 1eb5887 commit 2377a85

File tree

3 files changed

+80
-21
lines changed

3 files changed

+80
-21
lines changed

tests/resources/httpinfo.py

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
"""
2+
Simple webserver to respond with an echo of the sent request. It can listen to
3+
either a tcp port or a unix socket.
4+
"""
5+
import argparse
6+
import socket
7+
from pathlib import Path
18
from http.server import HTTPServer, BaseHTTPRequestHandler
2-
import sys
39

410
class EchoRequestInfo(BaseHTTPRequestHandler):
511
def do_GET(self):
@@ -9,9 +15,31 @@ def do_GET(self):
915
self.wfile.write('{}\n'.format(self.requestline).encode())
1016
self.wfile.write('{}\n'.format(self.headers).encode())
1117

18+
def address_string(self):
19+
"""
20+
Overridden to fix logging when serving on Unix socket.
21+
22+
FIXME: There are still broken pipe messages showing up in the jupyter
23+
server logs when running tests with the unix sockets.
24+
"""
25+
if isinstance(self.client_address, str):
26+
return self.client_address # Unix sock
27+
return super().address_string()
28+
29+
30+
class HTTPUnixServer(HTTPServer):
31+
address_family = socket.AF_UNIX
32+
1233

1334
if __name__ == '__main__':
14-
port = int(sys.argv[1])
15-
server_address = ('', port)
16-
httpd = HTTPServer(server_address, EchoRequestInfo)
35+
ap = argparse.ArgumentParser()
36+
ap.add_argument('--port', type=int)
37+
ap.add_argument('--unix-socket')
38+
args = ap.parse_args()
39+
40+
if args.unix_socket:
41+
Path(args.unix_socket).unlink(missing_ok=True)
42+
httpd = HTTPUnixServer(args.unix_socket, EchoRequestInfo)
43+
else:
44+
httpd = HTTPServer(('127.0.0.1', args.port), EchoRequestInfo)
1745
httpd.serve_forever()

tests/resources/jupyter_server_config.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,24 @@ def cats_only(response, path):
3030

3131
c.ServerProxy.servers = {
3232
'python-http': {
33-
'command': ['python3', './tests/resources/httpinfo.py', '{port}'],
33+
'command': ['python3', './tests/resources/httpinfo.py', '--port={port}'],
3434
},
3535
'python-http-abs': {
36-
'command': ['python3', './tests/resources/httpinfo.py', '{port}'],
36+
'command': ['python3', './tests/resources/httpinfo.py', '--port={port}'],
3737
'absolute_url': True
3838
},
3939
'python-http-port54321': {
40-
'command': ['python3', './tests/resources/httpinfo.py', '{port}'],
40+
'command': ['python3', './tests/resources/httpinfo.py', '--port={port}'],
4141
'port': 54321,
4242
},
4343
'python-http-mappath': {
44-
'command': ['python3', './tests/resources/httpinfo.py', '{port}'],
44+
'command': ['python3', './tests/resources/httpinfo.py', '--port={port}'],
4545
'mappath': {
4646
'/': '/index.html',
4747
}
4848
},
4949
'python-http-mappathf': {
50-
'command': ['python3', './tests/resources/httpinfo.py', '{port}'],
50+
'command': ['python3', './tests/resources/httpinfo.py', '--port={port}'],
5151
'mappath': mappathf,
5252
},
5353
'python-websocket' : {
@@ -56,8 +56,21 @@ def cats_only(response, path):
5656
'X-Custom-Header': 'pytest-23456',
5757
}
5858
},
59+
'python-unix-socket-true' : {
60+
'command': ['python3', './tests/resources/httpinfo.py', '--unix-socket={unix_socket}'],
61+
'unix_socket': True,
62+
},
63+
'python-unix-socket-file' : {
64+
'command': ['python3', './tests/resources/httpinfo.py', '--unix-socket={unix_socket}'],
65+
'unix_socket': "/tmp/jupyter-server-proxy-test-socket",
66+
},
67+
'python-unix-socket-file-no-command' : {
68+
# this server process can be started earlier by first interacting with
69+
# python-unix-socket-file
70+
'unix_socket': "/tmp/jupyter-server-proxy-test-socket",
71+
},
5972
'python-request-headers': {
60-
'command': ['python3', './tests/resources/httpinfo.py', '{port}'],
73+
'command': ['python3', './tests/resources/httpinfo.py', '--port={port}'],
6174
'request_headers_override': {
6275
'X-Custom-Header': 'pytest-23456',
6376
}
@@ -66,20 +79,20 @@ def cats_only(response, path):
6679
'command': ['python3', './tests/resources/gzipserver.py', '{port}'],
6780
},
6881
'python-http-rewrite-response': {
69-
'command': ['python3', './tests/resources/httpinfo.py', '{port}'],
82+
'command': ['python3', './tests/resources/httpinfo.py', '--port={port}'],
7083
'rewrite_response': translate_ciao,
7184
'port': 54323,
7285
},
7386
'python-chained-rewrite-response': {
74-
'command': ['python3', './tests/resources/httpinfo.py', '{port}'],
87+
'command': ['python3', './tests/resources/httpinfo.py', '--port={port}'],
7588
'rewrite_response': [translate_ciao, hello_to_foo],
7689
},
7790
'python-cats-only-rewrite-response': {
78-
'command': ['python3', './tests/resources/httpinfo.py', '{port}'],
91+
'command': ['python3', './tests/resources/httpinfo.py', '--port={port}'],
7992
'rewrite_response': [dog_to_cat, cats_only],
8093
},
8194
'python-dogs-only-rewrite-response': {
82-
'command': ['python3', './tests/resources/httpinfo.py', '{port}'],
95+
'command': ['python3', './tests/resources/httpinfo.py', '--port={port}'],
8396
'rewrite_response': [cats_only, dog_to_cat],
8497
},
8598
'python-proxyto54321-no-command': {

tests/test_proxies.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,36 @@ def request_get(port, path, token, host='localhost'):
2222
return h.getresponse()
2323

2424

25-
def test_server_proxy_minimal_proxy_path_encoding():
25+
@pytest.mark.parametrize(
26+
'server_process_path',
27+
[
28+
"/python-http/",
29+
"/python-unix-socket-true/",
30+
"/python-unix-socket-file/",
31+
"/python-unix-socket-file-no-command/",
32+
],
33+
)
34+
def test_server_proxy_minimal_proxy_path_encoding(server_process_path):
2635
"""Test that we don't encode anything more than we must to have a valid web
2736
request."""
2837
special_path = quote("Hello world 123 åäö 🎉你好世界±¥ :/[]@!$&'()*+,;=-._~?key1=value1", safe=":/?#[]@!$&'()*+,;=-._~")
29-
test_url = '/python-http/' + special_path
38+
test_url = server_process_path + special_path
3039
r = request_get(PORT, test_url, TOKEN)
3140
assert r.code == 200
3241
s = r.read().decode('ascii')
3342
assert 'GET /{}&token='.format(special_path) in s
3443

3544

36-
def test_server_proxy_hash_sign_encoding():
45+
@pytest.mark.parametrize(
46+
'server_process_path',
47+
[
48+
"/python-http/",
49+
"/python-unix-socket-true/",
50+
"/python-unix-socket-file/",
51+
"/python-unix-socket-file-no-command/",
52+
],
53+
)
54+
def test_server_proxy_hash_sign_encoding(server_process_path):
3755
"""
3856
FIXME: This is a test to establish the current behavior, but if it should be
3957
like this is a separate question not yet addressed.
@@ -44,23 +62,23 @@ def test_server_proxy_hash_sign_encoding():
4462

4563
# Case 0: a reference case
4664
path = "?token={}".format(TOKEN)
47-
h.request('GET', '/python-http/' + path)
65+
h.request('GET', server_process_path + path)
4866
r = h.getresponse()
4967
assert r.code == 200
5068
s = r.read().decode('ascii')
5169
assert 'GET /{} '.format(path) in s
5270

5371
# Case 1: #bla?token=secret -> everything following # ignored -> redirect because no token
5472
path = "#bla?token={}".format(TOKEN)
55-
h.request('GET', '/python-http/' + path)
73+
h.request('GET', server_process_path + path)
5674
r = h.getresponse()
5775
assert r.code == 200
5876
s = r.read().decode('ascii')
5977
assert 'GET / ' in s
6078

6179
# Case 2: %23bla?token=secret -> %23 is # -> everything following # ignored -> redirect because no token
6280
path = "%23?token={}".format(TOKEN)
63-
h.request('GET', '/python-http/' + path)
81+
h.request('GET', server_process_path + path)
6482
r = h.getresponse()
6583
assert r.code == 200
6684
s = r.read().decode('ascii')
@@ -79,7 +97,7 @@ def test_server_proxy_hash_sign_encoding():
7997
# return await self.proxy(self.port, path)
8098
# TypeError: object NoneType can't be used in 'await' expression
8199
path = "?token={}#test".format(TOKEN)
82-
h.request('GET', '/python-http/' + path)
100+
h.request('GET', server_process_path + path)
83101
r = h.getresponse()
84102
assert r.code == 302
85103
s = r.read().decode('ascii')

0 commit comments

Comments
 (0)