Here’s two different approaches to middleware we could have taken in Starlette:
ASGI middleware. Middleware classes present the ASGI interface. The ASGI scope is the state, and a request instance is an interface onto that state. Instantiating a request instance is a cheap operation.
Starlette-specific request/response middleware. Instantiate a request prior to running the middleware, and pass the same instance all the way through.
We’re using the first approach. A benefit is that Starlette middleware is really portable across different ASGI frameworks - you could be using a completely different framework, and still be able to Starlette middleware implementations with it.