]> git.ipfire.org Git - thirdparty/starlette.git/commitdiff
Version 0.1.3
authorTom Christie <tom@tomchristie.com>
Tue, 26 Jun 2018 09:09:35 +0000 (10:09 +0100)
committerTom Christie <tom@tomchristie.com>
Tue, 26 Jun 2018 09:09:35 +0000 (10:09 +0100)
README.md
starlette/__init__.py
starlette/routing.py
tests/test_routing.py

index 91cdbafc3905fd205d2f0132bb462778dab1f2d3..f80bdb0e3717971a41cf8d9f2130b10ad3df0f8b 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-<p align="center">
-    <h1 align="center">Starlette</h1>
-</p>
+<h1 align="center">
+    Starlette
+</h1>
 <p align="center">
     <em>✨ The little ASGI library that shines. ✨</em>
 </p>
@@ -20,7 +20,7 @@
 
 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.
 
 **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
 
 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>
index f6104abf6d2d813285896053d0f945db429b8c60..4978c00d7eea37d81f250cb34e00b025dbdf9bb1 100644 (file)
@@ -9,9 +9,12 @@ __all__ = (
     "asgi_application",
     "HTMLResponse",
     "JSONResponse",
+    "Path",
+    "PathPrefix",
     "Response",
+    "Router",
     "StreamingResponse",
     "Request",
     "TestClient",
 )
-__version__ = "0.1.2"
+__version__ = "0.1.3"
index 31694b6027a5ef3073a1d5a720d6a5c6b972f8e4..4c47f35398e585134561a7db648b83decc02de53 100644 (file)
@@ -20,7 +20,7 @@ class Path(Route):
         self.app = app
         self.methods = methods
         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)
 
     def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:
index c44b25b8237eaac5bfdcb64d0656e68fdecd8596..2a30c814578f91e22fe72282098f88555b718595 100644 (file)
@@ -14,12 +14,19 @@ def user(scope):
     return Response(content, media_type="text/plain")
 
 
+def staticfiles(scope):
+    return Response("xxxxx", media_type="image/png")
+
+
 app = Router(
     [
-        Path("/", app=homepage),
+        Path("/", app=homepage, methods=['GET']),
         PathPrefix(
             "/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.text == "Hello, world"
 
+    response = client.post("/")
+    assert response.status_code == 406
+    assert response.text == "Method not allowed"
+
     response = client.get("/foo")
     assert response.status_code == 404
     assert response.text == "Not found"
@@ -42,3 +53,11 @@ def test_router():
     response = client.get("/users/tomchristie")
     assert response.status_code == 200
     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"