From ca7d348e2c06763913d12e2b76feb4eb4f699d8d Mon Sep 17 00:00:00 2001 From: Changaco Date: Wed, 30 Jan 2019 09:54:34 +0100 Subject: [PATCH] patch Pando 0.45 to fix request parsing --- liberapay/main.py | 30 +++++++++++++++++++++++++++--- tests/py/test_state_chain.py | 5 ----- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/liberapay/main.py b/liberapay/main.py index d5c41662f8..e089b62b30 100644 --- a/liberapay/main.py +++ b/liberapay/main.py @@ -4,7 +4,7 @@ import signal import string from threading import Timer -import urllib +from urllib.parse import quote as urlquote, quote_plus as urlquote_plus, urlencode import aspen import aspen.http.mapping @@ -28,7 +28,7 @@ from liberapay.models.repository import refetch_repos from liberapay.security import authentication, csrf, set_default_security_headers from liberapay.utils import ( - b64decode_s, b64encode_s, erase_cookie, http_caching, set_cookie, urlquote, + b64decode_s, b64encode_s, erase_cookie, http_caching, set_cookie, ) from liberapay.utils.emails import handle_email_bounces from liberapay.utils.state_chain import ( @@ -225,7 +225,7 @@ def _Querystring_derive(self, **kw): new_qs = aspen.http.mapping.Mapping(self) for k, v in kw.items(): new_qs[k] = v - return '?' + urllib.parse.urlencode(new_qs, doseq=True) + return '?' + urlencode(new_qs, doseq=True) aspen.http.request.Querystring.derive = _Querystring_derive if hasattr(pando.http.request.Request, 'source'): @@ -368,3 +368,27 @@ def _decode_body(self): body = self.body return body.decode('utf8') if isinstance(body, bytes) else body pando.Response.text = property(_decode_body) + +# The monkey-patch below is only for Pando 0.45, it should be removed after that +def make_franken_uri(path, qs): + if path: + try: + if type(path) is bytes: + path.decode('ascii') + else: + path = path.encode('ascii') + except UnicodeError: + path = urlquote(path, '%/').encode('ascii') + + if qs: + try: + if type(qs) is bytes: + qs.decode('ascii') + else: + qs = qs.encode('ascii') + except UnicodeError: + qs = urlquote_plus(qs, '%=&').encode('ascii') + qs = b'?' + qs + + return path + qs +pando.http.request.make_franken_uri = make_franken_uri diff --git a/tests/py/test_state_chain.py b/tests/py/test_state_chain.py index cd8f0bc69a..d7656babbd 100644 --- a/tests/py/test_state_chain.py +++ b/tests/py/test_state_chain.py @@ -2,7 +2,6 @@ from pando.http.request import Request from pando.http.response import Response -import pytest from liberapay.security import csrf from liberapay.testing import Harness @@ -201,9 +200,7 @@ def test_quoted_unicode_path_is_okay(self): r = self.client.GET('', PATH_INFO='/about/%C3%A9', raise_immediately=False) assert r.code == 404, r.text - @pytest.mark.xfail def test_unquoted_unicode_path_is_okay(self): - # These fail because of bugs in Pando r = self.client.GET('/about/é'.encode('utf8'), raise_immediately=False) assert r.code == 404, r.text r = self.client.GET('', PATH_INFO='/about/é', raise_immediately=False) @@ -215,9 +212,7 @@ def test_quoted_unicode_querystring_is_okay(self): r = self.client.GET('/', QUERY_STRING='%C3%A9=%C3%A9', raise_immediately=False) assert r.code == 200, r.text - @pytest.mark.xfail def test_unquoted_unicode_querystring_is_okay(self): - # These fail because of bugs in Pando r = self.client.GET('/', QUERY_STRING='é=é'.encode('utf8'), raise_immediately=False) assert r.code == 200, r.text r = self.client.GET('/', QUERY_STRING='é=é', raise_immediately=False)