From 02b9a0a29765f75e92760558975656d0b361f9b7 Mon Sep 17 00:00:00 2001 From: Suby Raman Date: Sat, 14 Jan 2017 00:41:54 -0500 Subject: [PATCH] add redirect code from @pcdinh --- sanic/response.py | 26 ++++++++++++++++++ tests/test_requests.py | 62 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/sanic/response.py b/sanic/response.py index f2eb02e5..f6422d5f 100644 --- a/sanic/response.py +++ b/sanic/response.py @@ -169,3 +169,29 @@ async def file(location, mime_type=None, headers=None): headers=headers, content_type=mime_type, body_bytes=out_stream) + + +def redirect(to, headers=None, status=302, + content_type=None): + """ + Aborts execution and causes a 302 redirect (by default). + + :param to: path or fully qualified URL to redirect to + :param headers: optional dict of headers to include in the new request + :param status: status code (int) of the new request, defaults to 302 + :param content_type: + the content type (string) of the response, defaults to None + :returns: the redirecting Response + """ + if not content_type: + content_type = "text/html; charset=utf-8" + + headers = headers or {} + + # According to RFC 7231, a relative URI is now permitted. + headers['Location'] = to + + return HTTPResponse( + status=status, + headers=headers, + content_type=content_type) diff --git a/tests/test_requests.py b/tests/test_requests.py index ead76424..2cb41636 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -1,9 +1,10 @@ from json import loads as json_loads, dumps as json_dumps from sanic import Sanic -from sanic.response import json, text +from sanic.response import json, text, redirect from sanic.utils import sanic_endpoint_test from sanic.exceptions import ServerError +import pytest # ------------------------------------------------------------ # # GET @@ -188,3 +189,62 @@ def test_post_form_multipart_form_data(): request, response = sanic_endpoint_test(app, data=payload, headers=headers) assert request.form.get('test') == 'OK' + + +@pytest.fixture +def redirect_app(): + app = Sanic('test_get_then_redirect_01') + + @app.route('/redirect_init') + async def redirect_init(request): + return redirect("/redirect_target") + + @app.route('/redirect_init_with_301') + async def redirect_init_with_301(request): + return redirect("/redirect_target", status=301) + + @app.route('/redirect_target') + async def redirect_target(request): + return text('OK') + + return app + + +def test_redirect_default_302(redirect_app): + """ + We expect a 302 default status code and the headers to be set. + """ + request, response = sanic_endpoint_test( + redirect_app, method="get", + uri="/redirect_init", + allow_redirects=False) + + assert response.status == 302 + assert response.headers["Location"] == "/redirect_target" + assert response.headers["Content-Type"] == 'text/html; charset=utf-8' + + +def test_redirect_with_301(redirect_app): + """ + Test redirection with a different status code. + """ + request, response = sanic_endpoint_test( + redirect_app, method="get", + uri="/redirect_init_with_301", + allow_redirects=False) + + assert response.status == 301 + assert response.headers["Location"] == "/redirect_target" + + +def test_get_then_redirect_follow_redirect(redirect_app): + """ + With `allow_redirects` we expect a 200. + """ + response = sanic_endpoint_test( + redirect_app, method="get", + uri="/redirect_init", gather_request=False, + allow_redirects=True) + + assert response.status == 200 + assert response.text == 'OK'