Closed schnittstabil closed 7 years ago
Updated, sorry for the empty issue in the meanwhile. @weierophinney, @shadowhand, @mindplay-dk, @alamin3000: ping
I think we've already debated this to death and the current interfaces are fine.
Anyone else @http-interop/http-middleware-contributors ?
Both concepts, the pipe and the stack are used to describe Middleware Containers. Both container types share the idea of a reusable middlewares. Currently, the interfaces are:
I will describe both types, how they are used and how they could be reused. Based on that, I will show their commonalities and propose new interface versions. I consider neither the method names (
process
vsdispatch
vs__invoke
) nor the name sharing. Hence, please, don't try to start a new debate about that here.The Pipe(line)
The idea can be described as follows: Middlewares are small pipes, we plumb them together and pour a
$request
into top ending of the resulting pipe(line). The$request
may pass all middlewares and run out at the bottom. Thus we need some$finalHandler
to handle that:If we dispatch a
$request
it may pass all middlewares in the order:$m0
to$m3
.Similar to plumbing, the order of the pipes matters, but not the order we connect the pipes. Thus we could reuse plumbed pipes with other pipes:
If a
$request
runs out of$m0
the outerPipe
pours it into the inner one. Furthermore, if a$request
runs out of the innerPipe
the outerPipe
can pour it into$m3
.This means dispatching a
$request
should probably look like:The Stack
Stacks provide only two methods:
push
andpop
. Thus, if we have a stack and want to access the bottom element, we need to pop all elements above it before. This leads to the onion style of the middleware stack: We start with a final handler, i.e. the core of the onion. Then we push middlewares onto the stack, i.e. we wrap the core with new scales. Hence, we cannot access the inner scales this leads to the following setup:As we push middlewares onto the stack, the order must be reversed to get the same execution order as above.
Onions protect their inner scales, thus they could also be reused:
Commonalities
The
$finalHandler
Both use a
$finalHandler
with a signature, which can be described by:In some pipe implementations the
$finalHandler
is only called in case of an error, i.e. middlewares produce the requested content and the$finalHandler
handles the situation where no such content middleware is available.In the world of middleware stacks, that is not need: creating a Stack without a
$finalHandler
is not possible. Thus, the$finalHandler
is used to create the requested content.But both
$finalHandler
versions have one thing in common: They handle a request and return a response. Therefore, we may use the following interface for both versions:The
DelegateInterface
To dispatch a middleware (pipe/stack), we need to create a delegate object which knows the current pipe/stack:
Thus, the
$theNextMiddleware
can interact with a delegate of the pipe/stack and doesn't have to know how to dispatch the next middleware:But, as the middleware delegates the
$request
to the pipe/stack, it essentially does:That's really confusing, because the first
delegate
means something quiet different than the seconddelegate
. Furthermore,ServerMiddlewareInterface
andDelegateInterface
states that a delegate is somehow connected to a concrete middleware pipe/stack, but we can neither accesspush
nordispatch
. Instead we have:That is the same functionality
RequestHandlerInterface
provides: process a request and return a response. Only the$request
typehint differs for legacy reasons.New versions
The observations above leads to more general versions:
Conclusion
The pros, I see:
ServerMiddlewareInterface
orRequestHandlerInterface
, respectively.The cons, I see:
Best regards Michael