Skip to content

Commit 5f43b9f

Browse files
authored
Merge pull request #186 from consideRatio/fix-bug-by-minimal-quoting
Quote as little as needed for a valid proxied web request
2 parents 315d029 + 7cac307 commit 5f43b9f

File tree

3 files changed

+32
-6
lines changed

3 files changed

+32
-6
lines changed

.travis.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
language: python
22
python:
33
- 3.5
4+
- 3.6
5+
- 3.7
6+
- 3.8
47

5-
script:
8+
install:
69
- pip3 install .
710
- pip3 install pytest
11+
script:
812
- JUPYTER_TOKEN=secret jupyter-notebook --config=./tests/resources/jupyter_server_config.py &
913
- sleep 5
10-
- pytest
14+
- pytest -v

jupyter_server_proxy/handlers.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,14 @@ def get_client_uri(self, protocol, host, port, proxied_path):
141141
else:
142142
client_path = proxied_path
143143

144-
client_path = quote(client_path)
144+
# Quote spaces, åäö and such, but only enough to send a valid web
145+
# request onwards. To do this, we mark the RFC 3986 specs' "reserved"
146+
# and "un-reserved" characters as safe that won't need quoting. The
147+
# un-reserved need to be marked safe to ensure the quote function behave
148+
# the same in py36 as py37.
149+
#
150+
# ref: https://tools.ietf.org/html/rfc3986#section-2.2
151+
client_path = quote(client_path, safe=":/?#[]@!$&'()*+,;=-._~")
145152

146153
client_uri = '{protocol}://{host}:{port}{path}'.format(
147154
protocol=protocol,

tests/test_proxies.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,28 @@ def request_get(port, path, token, host='localhost'):
2020
return h.getresponse()
2121

2222

23-
def test_server_proxy_url_encoding():
24-
special_path = quote('Hellö Wörld 🎉你好世界@±¥')
23+
def test_server_proxy_minimal_proxy_path_encoding():
24+
"""Test that we don't encode anything more than we must to have a valid web
25+
request."""
26+
special_path = quote("Hello world 123 åäö 🎉你好世界±¥ :/[]@!$&'()*+,;=-._~", safe=":/?#[]@!$&'()*+,;=-._~")
27+
# NOTE: we left out ?# as they would interact badly with our requests_get
28+
# function's ability to pass the token query parameter.
2529
test_url = '/python-http/' + special_path
2630
r = request_get(PORT, test_url, TOKEN)
2731
assert r.code == 200
2832
s = r.read().decode('ascii')
29-
assert s.startswith('GET /{}?token='.format(special_path))
33+
assert 'GET /{}?token='.format(special_path) in s
34+
35+
def test_server_proxy_minimal_proxy_path_encoding_complement():
36+
"""Test that we don't encode ?# as a complement to the other test."""
37+
test_url = '/python-http/?token={}#test'.format(TOKEN)
38+
h = HTTPConnection('localhost', PORT, 10)
39+
r = request_get(PORT, test_url, TOKEN)
40+
h.request('GET', test_url)
41+
return h.getresponse()
42+
assert r.code == 200
43+
s = r.read().decode('ascii')
44+
assert 'GET /{}?token='.format(test_url) in s
3045

3146

3247
def test_server_proxy_non_absolute():

0 commit comments

Comments
 (0)