-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathfunction.py
More file actions
99 lines (76 loc) · 3.02 KB
/
Copy pathfunction.py
File metadata and controls
99 lines (76 loc) · 3.02 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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import typing as t
from ellar.common.interfaces import IHostContext
from ellar.common.types import ASGIApp, TReceive, TScope, TSend
from ellar.core.execution_context import current_connection
from starlette.responses import Response
from .middleware import EllarMiddleware
AwaitableCallable = t.Callable[..., t.Awaitable]
DispatchFunction = t.Callable[
[IHostContext, AwaitableCallable], t.Awaitable[t.Optional[Response]]
]
T = t.TypeVar("T")
class FunctionBasedMiddleware:
"""
Converts a function to an ASGI Middleware
Usage: Example 1 in @Module()
@middleware()
async def my_middleware(cls, context: IExecutionContext, 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()
async def my_middleware(context: IExecutionContext, call_next):
print("Called my_middleware")
response = context.switch_to_http_connection().get_response()
response.content = "Some Content"
response.status_code = 200
return response
Usage 3: Plain
async def asgi_middleware(execution_context: IExecutionContext, call_next):
#Run some actions
await call_next()
Middleware(FunctionBasedMiddleware, dispatch=asgi_middleware)
"""
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
async def call_next() -> None:
await self.app(scope, receive, send)
response = await self.dispatch_function(current_connection, call_next)
if response and isinstance(response, Response):
await response(scope, receive, send)
@t.no_type_check
def as_middleware(f: t.Callable) -> EllarMiddleware:
"""
Convert function to Functional Middleware ready to be used in application middleware
:param f: middleware callback function
:return: EllarMiddleware
eg:
@as_middleware
async def session_middleware(
context: IHostContext, call_next: t.Callable[..., t.Coroutine]
):
connection = context.switch_to_http_connection().get_client()
db_service = context.get_service_provider().get(EllarSQLService)
session = db_service.session_factory()
connection.state.session = session
await call_next()
# in Config.py
MIDDLEWARE = [
...,
session_middleware
]
"""
return EllarMiddleware(FunctionBasedMiddleware, dispatch=f)