Skip to content

Commit

Permalink
Merge pull request #261 from Pylons/bugfix/uri_parsing
Browse files Browse the repository at this point in the history
Bugfix: uri parsing
  • Loading branch information
digitalresistor committed Aug 27, 2019
2 parents 94e2311 + 2bd372a commit e247c93
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 4 deletions.
14 changes: 14 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
1.3.1 (2019-08-27)
------------------

Bugfixes
~~~~~~~~

- Waitress won't accidentally throw away part of the path if it starts with a
double slash (``GET //testing/whatever HTTP/1.0``). WSGI applications will
now receive a ``PATH_INFO`` in the environment that contains
``//testing/whatever`` as required. See
https://github.com/Pylons/waitress/issues/260 and
https://github.com/Pylons/waitress/pull/261


1.3.0 (2019-04-22)
------------------

Expand Down
28 changes: 24 additions & 4 deletions waitress/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,30 @@ def close(self):
def split_uri(uri):
# urlsplit handles byte input by returning bytes on py3, so
# scheme, netloc, path, query, and fragment are bytes
try:
scheme, netloc, path, query, fragment = urlparse.urlsplit(uri)
except UnicodeError:
raise ParsingError('Bad URI')

scheme = netloc = path = query = fragment = b''

# urlsplit below will treat this as a scheme-less netloc, thereby losing
# the original intent of the request. Here we shamelessly stole 4 lines of
# code from the CPython stdlib to parse out the fragment and query but
# leave the path alone. See
# https://github.com/python/cpython/blob/8c9e9b0cd5b24dfbf1424d1f253d02de80e8f5ef/Lib/urllib/parse.py#L465-L468
# and https://github.com/Pylons/waitress/issues/260

if uri[:2] == b'//':
path = uri

if b'#' in path:
path, fragment = path.split(b'#', 1)

if b'?' in path:
path, query = path.split(b'?', 1)
else:
try:
scheme, netloc, path, query, fragment = urlparse.urlsplit(uri)
except UnicodeError:
raise ParsingError('Bad URI')

return (
tostr(scheme),
tostr(netloc),
Expand Down
24 changes: 24 additions & 0 deletions waitress/tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,30 @@ def test_split_uri_unicode_error_raises_parsing_error(self):
except ParsingError:
pass

def test_split_uri_path(self):
self._callFUT(b'//testing/whatever')
self.assertEqual(self.path, '//testing/whatever')
self.assertEqual(self.proxy_scheme, '')
self.assertEqual(self.proxy_netloc, '')
self.assertEqual(self.query, '')
self.assertEqual(self.fragment, '')

def test_split_uri_path_query(self):
self._callFUT(b'//testing/whatever?a=1&b=2')
self.assertEqual(self.path, '//testing/whatever')
self.assertEqual(self.proxy_scheme, '')
self.assertEqual(self.proxy_netloc, '')
self.assertEqual(self.query, 'a=1&b=2')
self.assertEqual(self.fragment, '')

def test_split_uri_path_query_fragment(self):
self._callFUT(b'//testing/whatever?a=1&b=2#fragment')
self.assertEqual(self.path, '//testing/whatever')
self.assertEqual(self.proxy_scheme, '')
self.assertEqual(self.proxy_netloc, '')
self.assertEqual(self.query, 'a=1&b=2')
self.assertEqual(self.fragment, 'fragment')

class Test_get_header_lines(unittest.TestCase):

def _callFUT(self, data):
Expand Down

0 comments on commit e247c93

Please sign in to comment.