summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBert JW Regeer <bertjw@regeer.org>2019-08-27 14:36:05 -0600
committerGitHub <noreply@github.com>2019-08-27 14:36:05 -0600
commite247c93ce932c0184c5242d451e5776b17a20d21 (patch)
tree1800a88a481b54395d44b89151f48cd4fa9ec04d
parent94e23114bf4e8db9507f3550294037a4804eb053 (diff)
parent2bd372a52c2e2f18258e593885c16db68172ff1b (diff)
downloadwaitress-e247c93ce932c0184c5242d451e5776b17a20d21.tar.gz
Merge pull request #261 from Pylons/bugfix/uri_parsing
Bugfix: uri parsing
-rw-r--r--CHANGES.txt14
-rw-r--r--waitress/parser.py28
-rw-r--r--waitress/tests/test_parser.py24
3 files changed, 62 insertions, 4 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 01fe6f3..f511dbb 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -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)
------------------
diff --git a/waitress/parser.py b/waitress/parser.py
index e85ede2..6ee700e 100644
--- a/waitress/parser.py
+++ b/waitress/parser.py
@@ -253,10 +253,30 @@ class HTTPRequestParser(object):
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),
diff --git a/waitress/tests/test_parser.py b/waitress/tests/test_parser.py
index cf4a976..920de96 100644
--- a/waitress/tests/test_parser.py
+++ b/waitress/tests/test_parser.py
@@ -259,6 +259,30 @@ class Test_split_uri(unittest.TestCase):
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):