-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathfunction.py
More file actions
68 lines (52 loc) · 2.2 KB
/
Copy pathfunction.py
File metadata and controls
68 lines (52 loc) · 2.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import typing as t
from starlette.responses import Response
from ellar.common.interfaces import IHostContext, IHostContextFactory
from ellar.common.types import ASGIApp, TReceive, TScope, TSend
from ellar.core.connection import HTTPConnection
AwaitableCallable = t.Callable[..., t.Awaitable]
DispatchFunction = t.Callable[
[IHostContext, AwaitableCallable], t.Awaitable[t.Optional[Response]]
]
T = t.TypeVar("T")
class FunctionBasedMiddleware:
"""
Convert ASGI Middleware to a Node-like Middleware.
Usage: Example 1
@middleware()
def my_middleware(context: IExecution, call_next):
print("Called my_middleware")
request = context.switch_to_http_connection().get_request()
request.state.my_middleware = True
await call_next()
Usage: Example 2
@middleware()
def my_middleware(context: IExecution, call_next):
print("Called my_middleware")
response = context.switch_to_http_connection().get_response()
response.content = "Some Content"
response.status_code = 200
return response
"""
def __init__(
self, app: ASGIApp, dispatch: t.Optional[DispatchFunction] = None
) -> None:
self.app = app
self.dispatch_function = dispatch or self.dispatch
async def dispatch(
self, context: IHostContext, call_next: AwaitableCallable
) -> Response:
raise NotImplementedError() # pragma: no cover
async def __call__(self, scope: TScope, receive: TReceive, send: TSend) -> None:
if scope["type"] not in ("http", "websocket"):
await self.app(scope, receive, send)
return
connection = HTTPConnection(scope, receive)
if not connection.service_provider: # pragma: no cover
raise Exception("Service Provider is required")
context_factory = connection.service_provider.get(IHostContextFactory)
context = context_factory.create_context(scope, receive, send)
async def call_next() -> None:
await self.app(scope, receive, send)
response = await self.dispatch_function(context, call_next)
if response and isinstance(response, Response):
await response(scope, receive, send)