Version 0.1.3

This commit is contained in:
Tom Christie 2018-06-26 10:09:35 +01:00
parent 6334642731
commit 4f80753cf7
4 changed files with 72 additions and 8 deletions

View File

@ -1,6 +1,6 @@
<p align="center"> <h1 align="center">
<h1 align="center">Starlette</h1> Starlette
</p> </h1>
<p align="center"> <p align="center">
<em>✨ The little ASGI library that shines. ✨</em> <em>✨ The little ASGI library that shines. ✨</em>
</p> </p>
@ -20,7 +20,7 @@
Starlette is a small library for working with [ASGI](https://asgi.readthedocs.io/en/latest/). Starlette is a small library for working with [ASGI](https://asgi.readthedocs.io/en/latest/).
It gives you `Request` and `Response` classes, a test client, and a It gives you `Request` and `Response` classes, routing, a test client, and a
decorator for writing super-minimal applications. decorator for writing super-minimal applications.
**Requirements:** **Requirements:**
@ -221,6 +221,48 @@ raise an error.
--- ---
## Routing
Starlette includes a `Router` class which is an ASGI application that
dispatches to other ASGI applications.
```python
from starlette import Router, Path, PathPrefix
from myproject import Homepage, StaticFiles
app = Router([
Path('/', app=Homepage, methods=['GET']),
PathPrefix('/static', app=StaticFiles, methods=['GET'])
])
```
Paths can use URI templating style to capture path components.
```python
Path('/users/{username}', app=User, methods=['GET'])
```
Path components are made available in the scope, as `scope["kwargs"]`.
Because each target of the router is an ASGI instance itself, routers
allow for easy composition. For example:
```python
app = Router([
Path('/', app=Homepage, methods=['GET']),
PathPrefix('/users', app=Router([
Path('/', app=Users, methods=['GET', 'POST']),
Path('/{username}', app=User, methods=['GET']),
]))
])
```
The router will respond with "404 Not found" or "406 Method not allowed"
responses for requests which do not match.
---
## Test Client ## Test Client
The test client allows you to make requests against your ASGI application, The test client allows you to make requests against your ASGI application,
@ -264,4 +306,4 @@ async def app(request):
--- ---
<p align="center"><i>API Star is <a href="https://github.com/tomchristie/apistar/blob/master/LICENSE.md">BSD licensed</a> code.<br/>Designed & built in Brighton, England.</i><br/>&mdash; ⭐️ &mdash;</p> <p align="center"><i>Starlette is <a href="https://github.com/tomchristie/starlette/blob/master/LICENSE.md">BSD licensed</a> code.<br/>Designed & built in Brighton, England.</i><br/>&mdash; ⭐️ &mdash;</p>

View File

@ -9,9 +9,12 @@ __all__ = (
"asgi_application", "asgi_application",
"HTMLResponse", "HTMLResponse",
"JSONResponse", "JSONResponse",
"Path",
"PathPrefix",
"Response", "Response",
"Router",
"StreamingResponse", "StreamingResponse",
"Request", "Request",
"TestClient", "TestClient",
) )
__version__ = "0.1.2" __version__ = "0.1.3"

View File

@ -20,7 +20,7 @@ class Path(Route):
self.app = app self.app = app
self.methods = methods self.methods = methods
regex = "^" + path + "$" regex = "^" + path + "$"
regex = re.sub("{([a-zA-Z_][a-zA-Z0-9_]*)}", r"(?P<\1>[^/]*)", regex) regex = re.sub("{([a-zA-Z_][a-zA-Z0-9_]*)}", r"(?P<\1>[^/]+)", regex)
self.path_regex = re.compile(regex) self.path_regex = re.compile(regex)
def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]: def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:

View File

@ -14,12 +14,19 @@ def user(scope):
return Response(content, media_type="text/plain") return Response(content, media_type="text/plain")
def staticfiles(scope):
return Response("xxxxx", media_type="image/png")
app = Router( app = Router(
[ [
Path("/", app=homepage), Path("/", app=homepage, methods=['GET']),
PathPrefix( PathPrefix(
"/users", app=Router([Path("", app=users), Path("/{username}", app=user)]) "/users", app=Router([Path("", app=users), Path("/{username}", app=user)])
), ),
PathPrefix(
"/static", app=staticfiles, methods=['GET']
),
] ]
) )
@ -31,6 +38,10 @@ def test_router():
assert response.status_code == 200 assert response.status_code == 200
assert response.text == "Hello, world" assert response.text == "Hello, world"
response = client.post("/")
assert response.status_code == 406
assert response.text == "Method not allowed"
response = client.get("/foo") response = client.get("/foo")
assert response.status_code == 404 assert response.status_code == 404
assert response.text == "Not found" assert response.text == "Not found"
@ -42,3 +53,11 @@ def test_router():
response = client.get("/users/tomchristie") response = client.get("/users/tomchristie")
assert response.status_code == 200 assert response.status_code == 200
assert response.text == "User tomchristie" assert response.text == "User tomchristie"
response = client.get("/static/123")
assert response.status_code == 200
assert response.text == "xxxxx"
response = client.post("/static/123")
assert response.status_code == 406
assert response.text == "Method not allowed"