diff --git a/sanic/response.py b/sanic/response.py index cf9aaba2..c32ed9ce 100644 --- a/sanic/response.py +++ b/sanic/response.py @@ -421,7 +421,7 @@ def redirect( headers = headers or {} # URL Quote the URL before redirecting - safe_to = quote_plus(to, safe=":/#?&=@[]!$&'()*+,;") + safe_to = quote_plus(to, safe=":/%#?&=@[]!$&'()*+,;") # According to RFC 7231, a relative URI is now permitted. headers["Location"] = safe_to diff --git a/tests/test_redirect.py b/tests/test_redirect.py index f5efac60..8c7cc007 100644 --- a/tests/test_redirect.py +++ b/tests/test_redirect.py @@ -1,4 +1,6 @@ import pytest +import json +from urllib.parse import quote from sanic.response import text, redirect @@ -107,3 +109,25 @@ def test_redirect_with_header_injection(redirect_app): assert response.status == 302 assert "test-header" not in response.headers assert not response.text.startswith('test-body') + + +@pytest.mark.parametrize("test_str", ["sanic-test", "sanictest", "sanic test"]) +async def test_redirect_with_params(app, test_client, test_str): + + @app.route("/api/v1/test//") + async def init_handler(request, test): + assert test == test_str + return redirect("/api/v2/test/{}/".format(quote(test))) + + @app.route("/api/v2/test//") + async def target_handler(request, test): + assert test == test_str + return text("OK") + + test_cli = await test_client(app) + + response = await test_cli.get("/api/v1/test/{}/".format(quote(test_str))) + assert response.status == 200 + + txt = await response.text() + assert txt == "OK"