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) 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 ### StreamingResponse
Takes an async generator and streams the response body. Takes an async generator and streams the response body.

View File

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

View File

@ -49,6 +49,10 @@ class URL(str):
def port(self): def port(self):
return self.components.port 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. # Type annotations for valid `__init__` values to QueryParams and Headers.
StrPairs = typing.Sequence[typing.Tuple[str, str]] StrPairs = typing.Sequence[typing.Tuple[str, str]]

View File

@ -3,6 +3,7 @@ from email.utils import formatdate
from mimetypes import guess_type from mimetypes import guess_type
from starlette.datastructures import MutableHeaders from starlette.datastructures import MutableHeaders
from starlette.types import Receive, Send from starlette.types import Receive, Send
from urllib.parse import quote_plus
import aiofiles import aiofiles
import json import json
import hashlib import hashlib
@ -98,6 +99,12 @@ class JSONResponse(Response):
return json.dumps(content, **self.options).encode("utf-8") 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): class StreamingResponse(Response):
def __init__( def __init__(
self, self,

View File

@ -13,6 +13,9 @@ def test_url():
assert u.query == "abc=123" assert u.query == "abc=123"
assert u.params == "" assert u.params == ""
assert u.fragment == "anchor" 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(): 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 asyncio
import os import os
@ -29,6 +35,23 @@ def test_bytes_response():
assert response.content == b"xxxxx" 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 test_streaming_response():
def app(scope): def app(scope):
async def numbers(minimum, maximum): async def numbers(minimum, maximum):