mirror of https://github.com/encode/starlette.git
Add Router, Path, PathPrefix
This commit is contained in:
parent
5ab86e1522
commit
903e1b2fc5
|
@ -1,6 +1,7 @@
|
||||||
from starlette.decorators import asgi_application
|
from starlette.decorators import asgi_application
|
||||||
from starlette.response import HTMLResponse, JSONResponse, Response, StreamingResponse
|
from starlette.response import HTMLResponse, JSONResponse, Response, StreamingResponse
|
||||||
from starlette.request import Request
|
from starlette.request import Request
|
||||||
|
from starlette.routing import Path, PathPrefix, Router
|
||||||
from starlette.testclient import TestClient
|
from starlette.testclient import TestClient
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
from starlette import Response
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class Path:
|
||||||
|
def __init__(self, path, app):
|
||||||
|
self.path = path
|
||||||
|
self.app = app
|
||||||
|
regex = '^' + path + '$'
|
||||||
|
regex = re.sub('{([a-zA-Z_][a-zA-Z0-9_]*)}', r'(?P<\1>[^/]*)', regex)
|
||||||
|
self.path_regex = re.compile(regex)
|
||||||
|
|
||||||
|
def matches(self, scope):
|
||||||
|
match = self.path_regex.match(scope['path'])
|
||||||
|
if match:
|
||||||
|
kwargs = dict(scope.get('kwargs', {}))
|
||||||
|
kwargs.update(match.groupdict())
|
||||||
|
child_scope = scope.copy()
|
||||||
|
child_scope['kwargs'] = kwargs
|
||||||
|
return True, child_scope
|
||||||
|
return False, {}
|
||||||
|
|
||||||
|
def __call__(self, scope):
|
||||||
|
return self.app(scope)
|
||||||
|
|
||||||
|
|
||||||
|
class PathPrefix:
|
||||||
|
def __init__(self, path, app):
|
||||||
|
self.path = path
|
||||||
|
self.app = app
|
||||||
|
regex = '^' + path
|
||||||
|
regex = re.sub('{([a-zA-Z_][a-zA-Z0-9_]*)}', r'(?P<\1>[^/]*)', regex)
|
||||||
|
self.path_regex = re.compile(regex)
|
||||||
|
|
||||||
|
def matches(self, scope):
|
||||||
|
match = self.path_regex.match(scope['path'])
|
||||||
|
if match:
|
||||||
|
kwargs = dict(scope.get('kwargs', {}))
|
||||||
|
kwargs.update(match.groupdict())
|
||||||
|
child_scope = scope.copy()
|
||||||
|
child_scope['kwargs'] = kwargs
|
||||||
|
child_scope['root_path'] = scope.get('root_path', '') + match.string
|
||||||
|
child_scope['path'] = scope['path'][match.span()[1]:]
|
||||||
|
return True, child_scope
|
||||||
|
return False, {}
|
||||||
|
|
||||||
|
def __call__(self, scope):
|
||||||
|
return self.app(scope)
|
||||||
|
|
||||||
|
|
||||||
|
class Router:
|
||||||
|
def __init__(self, routes, default=None):
|
||||||
|
self.routes = routes
|
||||||
|
self.default = self.not_found if default is None else default
|
||||||
|
|
||||||
|
def __call__(self, scope):
|
||||||
|
for route in self.routes:
|
||||||
|
matched, child_scope = route.matches(scope)
|
||||||
|
if matched:
|
||||||
|
return route(child_scope)
|
||||||
|
return self.not_found(scope)
|
||||||
|
|
||||||
|
def not_found(self, scope):
|
||||||
|
return Response('Not found', 404, media_type='text/plain')
|
|
@ -0,0 +1,43 @@
|
||||||
|
from starlette import Response, Path, PathPrefix, Router, TestClient
|
||||||
|
|
||||||
|
|
||||||
|
def homepage(scope):
|
||||||
|
return Response('Hello, world', media_type='text/plain')
|
||||||
|
|
||||||
|
|
||||||
|
def users(scope):
|
||||||
|
return Response('All users', media_type='text/plain')
|
||||||
|
|
||||||
|
|
||||||
|
def user(scope):
|
||||||
|
content = 'User ' + scope['kwargs']['username']
|
||||||
|
return Response(content, media_type='text/plain')
|
||||||
|
|
||||||
|
|
||||||
|
app = Router([
|
||||||
|
Path('/', app=homepage),
|
||||||
|
PathPrefix('/users', app=Router([
|
||||||
|
Path('', app=users),
|
||||||
|
Path('/{username}', app=user),
|
||||||
|
]))
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def test_router():
|
||||||
|
client = TestClient(app)
|
||||||
|
|
||||||
|
response = client.get('/')
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.text == 'Hello, world'
|
||||||
|
|
||||||
|
response = client.get('/foo')
|
||||||
|
assert response.status_code == 404
|
||||||
|
assert response.text == 'Not found'
|
||||||
|
|
||||||
|
response = client.get('/users')
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.text == 'All users'
|
||||||
|
|
||||||
|
response = client.get('/users/tomchristie')
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.text == 'User tomchristie'
|
Loading…
Reference in New Issue