Redirect response (#39)

* Minor Request cleanups

* Black formatting

* Add RedirectResponse

* Black formatting

* Clean up test_redirect_response test case
This commit is contained in:
Tom Christie 2018-08-27 14:51:24 +01:00 committed by GitHub
parent e937ddc3d5
commit cb9fc8746b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 61 additions and 2 deletions

View File

@ -134,6 +134,26 @@ class App:
await response(receive, send)
```
### RedirectResponse
Returns an HTTP redirect. Uses a 302 status code by default.
```python
from starlette import PlainTextResponse, RedirectResponse
class App:
def __init__(self, scope):
self.scope = scope
async def __call__(self, receive, send):
if self.scope['path'] != '/':
response = RedirectResponse(url='/')
else:
response = PlainTextResponse('Hello, world!')
await response(receive, send)
```
### StreamingResponse
Takes an async generator and streams the response body.

View File

@ -3,6 +3,7 @@ from starlette.response import (
FileResponse,
HTMLResponse,
JSONResponse,
RedirectResponse,
Response,
PlainTextResponse,
StreamingResponse,
@ -17,9 +18,10 @@ __all__ = (
"HTMLResponse",
"JSONResponse",
"PlainTextResponse",
"RedirectResponse",
"Response",
"StreamingResponse",
"Request",
"TestClient",
)
__version__ = "0.1.16"
__version__ = "0.1.17"

View File

@ -49,6 +49,10 @@ class URL(str):
def port(self):
return self.components.port
def replace(self, **kwargs):
components = self.components._replace(**kwargs)
return URL(components.geturl())
# Type annotations for valid `__init__` values to QueryParams and Headers.
StrPairs = typing.Sequence[typing.Tuple[str, str]]

View File

@ -3,6 +3,7 @@ from email.utils import formatdate
from mimetypes import guess_type
from starlette.datastructures import MutableHeaders
from starlette.types import Receive, Send
from urllib.parse import quote_plus
import aiofiles
import json
import hashlib
@ -98,6 +99,12 @@ class JSONResponse(Response):
return json.dumps(content, **self.options).encode("utf-8")
class RedirectResponse(Response):
def __init__(self, url: str, status_code: int = 302, headers: dict = None) -> None:
super().__init__(content=b"", status_code=status_code, headers=headers)
self.headers["location"] = quote_plus(url, safe=":/#?&=@[]!$&'()*+,;")
class StreamingResponse(Response):
def __init__(
self,

View File

@ -13,6 +13,9 @@ def test_url():
assert u.query == "abc=123"
assert u.params == ""
assert u.fragment == "anchor"
new = u.replace(scheme="http")
assert new == "http://example.org:123/path/to/somewhere?abc=123#anchor"
assert new.scheme == "http"
def test_headers():

View File

@ -1,4 +1,10 @@
from starlette import FileResponse, Response, StreamingResponse, TestClient
from starlette.response import (
FileResponse,
RedirectResponse,
Response,
StreamingResponse,
)
from starlette.testclient import TestClient
import asyncio
import os
@ -29,6 +35,23 @@ def test_bytes_response():
assert response.content == b"xxxxx"
def test_redirect_response():
def app(scope):
async def asgi(receive, send):
if scope["path"] == "/":
response = Response("hello, world", media_type="text/plain")
else:
response = RedirectResponse("/")
await response(receive, send)
return asgi
client = TestClient(app)
response = client.get("/redirect")
assert response.text == "hello, world"
assert response.url == "http://testserver/"
def test_streaming_response():
def app(scope):
async def numbers(minimum, maximum):