From 264781c68ea477b4a27499e000b2530b595130f9 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Mon, 15 Jan 2018 19:25:01 +0200 Subject: [PATCH] Fix #2662: Properly unquote path parts --- CHANGES.rst | 6 ++++++ aiohttp/web_urldispatcher.py | 10 +++++----- requirements/ci-wheel.txt | 4 ++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 7b72bd3ad6f..4918174bf28 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -14,6 +14,12 @@ Changelog .. towncrier release notes start +2.3.8 (2018-01-15) +================== + +- Do not use `yarl.unquote` internal function in aiohttp. Fix + incorrectly unquoted path part in URL dispatcher (#2662) + 2.3.7 (2017-12-27) ================== diff --git a/aiohttp/web_urldispatcher.py b/aiohttp/web_urldispatcher.py index 96500e538d2..74d5d45f4ff 100644 --- a/aiohttp/web_urldispatcher.py +++ b/aiohttp/web_urldispatcher.py @@ -15,10 +15,10 @@ from pathlib import Path from types import MappingProxyType -# do not use yarl.quote directly, +# do not use yarl.quote/unquote directly, # use `URL(path).raw_path` instead of `quote(path)` # Escaping of the URLs need to be consitent with the escaping done by yarl -from yarl import URL, unquote +from yarl import URL from . import hdrs, helpers from .abc import AbstractMatchInfo, AbstractRouter, AbstractView @@ -427,7 +427,7 @@ def _match(self, path): if match is None: return None else: - return {key: unquote(value, unsafe='+') for key, value in + return {key: URL(value).path for key, value in match.groupdict().items()} def get_info(self): @@ -559,7 +559,7 @@ def resolve(self, request): if method not in allowed_methods: return None, allowed_methods - match_dict = {'filename': unquote(path[len(self._prefix)+1:])} + match_dict = {'filename': URL(path[len(self._prefix)+1:]).path} return (UrlMappingMatchInfo(match_dict, self._routes[method]), allowed_methods) yield # pragma: no cover @@ -572,7 +572,7 @@ def __iter__(self): @asyncio.coroutine def _handle(self, request): - filename = unquote(request.match_info['filename']) + filename = request.match_info['filename'] try: filepath = self._directory.joinpath(filename).resolve() if not self._follow_symlinks: diff --git a/requirements/ci-wheel.txt b/requirements/ci-wheel.txt index 7bd971fb4b0..0e595ce7572 100644 --- a/requirements/ci-wheel.txt +++ b/requirements/ci-wheel.txt @@ -7,14 +7,14 @@ cython==0.27.1 chardet==3.0.4 isort==4.2.15 tox==2.9.1 -multidict==3.3.0 +multidict==4.0.0 async-timeout==2.0.0 pytest==3.2.3 pytest-cov==2.5.1 pytest-mock==1.6.3 gunicorn==19.7.1 twine==1.9.1 -yarl==0.13.0 +yarl==1.0.0 brotlipy==0.7.0 # Using PEP 508 env markers to control dependency on runtimes: