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.response import HTMLResponse, JSONResponse, Response, StreamingResponse
|
||||
from starlette.request import Request
|
||||
from starlette.routing import Path, PathPrefix, Router
|
||||
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