Closed tombulled closed 1 year ago
Conceptually, every piece of middleware can take in one thing, and return one thing, aka Callable[[In], Out]
.
However, the user may want to provide a "funnel" to produce In
. Here's an example "funnel":
def build_request(method: str, path: str) -> Request:
return Request(method=method, path=path)
In the above example, build_request
would sit at the front of all of the middleware (and In
would become bound to Request
). A funnel is entirely optional, as the user might rock up with a Request
to begin with (in this case an identity function could represent the funnel).
Then, each middleware callable could look like this:
class RequestMiddleware(Protocol):
def __call__(self, request: Request, /) -> Response:
...
def do_something(call_next: RequestMiddleware, request: Request, /) -> Response:
request.headers["message"] = "Hello, World!"
return call_next(request)
However, none of the middleware should be responsible for converting a Request
into a Response
, instead a user-provided "sinc" should do this:
def send_request(request: Request, /) -> Response:
return httpx.request(request)
E.g. make
Middleware
generic (Middleware[In, Out]
)Each middleware function should have a type like this:
An entrypoint should look like this: