-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stacks are middlewares too #4
Stacks are middlewares too #4
Conversation
049ed40
to
3e3d5bb
Compare
I think I prefer the idea that a stack can also be a middleware. That allows for mixing of different dispatching systems (if they also follow the same methodology) and allows mixing groups of middleware that may be packaged together. However, the order of middleware is sometimes important and this may cause surprises. I need to think about it some more. Any thoughts @equip/contributors ? |
*/ | ||
public function __construct(array $middleware, callable $default) | ||
public function __construct(array $middleware, DelegateInterface $lastDelegate) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not correct. The default should not be a delegate, because this is perfectly acceptable for $default
:
$default = [$responseFactory, 'createResponse'];
{ | ||
array_map([$this, 'append'], $middleware); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You lost this, which destroys the ability to ensure type safety of middleware added by the constructor.
$delegate = new Delegate($this->middleware, $default); | ||
|
||
return $delegate->process($request); | ||
return $this->process($request, new CallableToDelegateAdapter($default)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, this is not right. The default is not a delegate.
d9dce30
to
4a48fa0
Compare
4a48fa0
to
19340e4
Compare
That is true, but not in this case. A container manages a group of middlewares, thus the order is only important within that container. For middleware stacks, where middlewares are called from last to first, it works like that: $stack = new Stack(...[
$middleware5,
$middleware4,
new Stack(...[
$middleware3,
$middleware2,
]),
$middleware1,
$middleware0,
]); If one mixes containers, e.g. with pipes, where middlewares are called from first to last, we get: $stack = new Pipe(...[
$middleware0,
$middleware1,
new Stack(...[
$middleware3,
$middleware2,
]),
$middleware4,
$middleware5,
]); It looks confusing, but it is the expected behavior. The order within the pipe and stack is correct according to their semantics. |
@shadowhand: lgtm – ready for review. |
But I just realized, that the |
* | ||
* @return ResponseInterface | ||
*/ | ||
public function process(ServerRequestInterface $request, DelegateInterface $nextContanierDelegate) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: nextContanierDelegate
should be nextContainerDelegate
@@ -50,9 +50,9 @@ $default = function (RequestInterface $request) { | |||
return new Response(); | |||
}; | |||
|
|||
$stack = new Stack($middleware, $default); | |||
$stack = new Stack(...$middleware); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not really sure about this change. What does splat buy us here? From a syntax standpoint, it is more to type out. From a functionality standpoint, all it does it splat and unsplat the arguments, which consumes ticks unnecessarily.
*/ | ||
public function process(ServerRequestInterface $request, DelegateInterface $nextContanierDelegate) | ||
{ | ||
$delegate = new Delegate($this->middleware, new DelegateToCallableAdapter($nextContanierDelegate)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, we're getting off track here. I want to see two changes, made as separate PRs:
- move
$default
to the constructor as the first argument - implement
ServerMiddlewareInterface
in Stack
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see – but that doesn't make sense in my opinion, e.g:
$inner = new Stack($default1, ...$middleware);
$outer = new Stack($default2, ...[
// …
$inner,
$nextMiddleware,
// …
]);
$outer->dispatch($request);
It is not only because we have to create two $default
functions/instances. It is also confusing, because it is not obvious, which $default
will be called. $default1
, $default2
or both?
Instead I suggest:
$inner = new Stack(...$middleware);
$outer = new Stack(...[
// …
$inner,
$nextMiddleware,
// …
]);
$outer->dispatch($request, $default);
Thus, I think it is more obvious that $inner
delegates the request to $outer
, which delegates the request to $nextMiddleware
.
Of course, in last version the splat became useless…
Okay cool. I'm going to take this as-is and then make some tweaks. Will make PR for you to check out. |
Stack is actually a middleware pipe. DelegateToCallableAdapter is actually a proxy. Refs #4
Stack is actually a middleware pipe. DelegateToCallableAdapter is actually a proxy. Refs #4
This is a consistent continuation of #2 and allows reusing
Stack
asServerMiddlewareInterface
in other Middleware containers:See #6 for deatils.