For clarification: I'm still undecided about the usefulness of the two
modifier interfaces (described in this thread as "$request = $foo
->modify($request);" and "$response = $foo->modify($response);"). I've
added them to the hms proposal
<https://github.com/http-message-strategies-interop/fig-standards/blob/http-message-strategies/proposed/http-message-strategies/http-message-strategies-meta.md>
to
make them discussable and to explore their pros and cons. As Rasmus
suggested, they will be removed within the next few days because the
ActionInterface/HandlerInterface can stand on its on.
On Saturday, May 20, 2017 at 10:33:33 PM UTC+2, Matthieu Napoli wrote:
> Rasmus:
>
> I can see the handler-interface having 3 uses in the context of PSR-15:
>> …
>> 3. As type-hint for the "final" handler supported by many dispatchers.
>
> 3. I agree this is a bit of an ugly detail and it would be better if we
> could do without, but honestly this is just a detail, and it works, and
> it's not really a practical problem, I don't see how a PSR would matter here
>
That PSR would also allow interop of routers, controllers and final
handlers, and indeed solve practical problems, e.g. if you use it with your
pipe function:
// diff in pseudo code:
- function pipe(MiddlewareOrHandler[] stack) : Middleware {}
+ function pipe(Middleware[] stack, Handler $final) : Handler {}
- function router(array routes) : Middleware {}
+ function router(array routes) : Handler {}
Thus you do not need to fabricate handlers like the one at your
Router::dispatch
<https://github.com/stratifyphp/router/blob/779a77b6b8078fa3cb2fe86a3361c43b06df94e0/src/Router.php#L83-L85>,
and
the code of your example becomes bit more explicit:
$application = pipe([
ErrorHandlerMiddleware::class,
ForceHttpsMiddleware::class,
], prefix([
'/api/' => pipe([
HttpAuthenticationMiddleware::class,
], router([
'/api/articles' => /* controller */,
'/api/articles/{id}' => /* controller */,
])),
'/' => pipe([
MaintenanceModeMiddleware::class,
SessionMiddleware::class,
DebugBarMiddleware::class,
], router([
'/' => /* controller */,
'/article/{id}' => /* controller */,
])),
]));
As you can see, there is no essential difference for the end user setup.
Although, we do not need to create those meaningless $next delegates: the
prefix and router functions return them.
And yes the router will be invoked with a $next, but IMO that's a good
> thing: the router can call $next if the URL doesn't match any route
> <https://github.com/stratifyphp/router/blob/master/src/Router.php#L58-L63>.
> That allows, for example, to use several routers in a single pipe (e.g. if
> you have modules).
>
I disagree, that's not a good thing, this means $next would be used
differently by different middlewares:
For example for your HttpAuthenticationMiddleware, calling $next means:
everything is fine; lets carry out the real task and if that fails I will
try to handle that.
For the router you're suggesting, calling $next means: something went
wrong; lets delegate the task to someone else and if that fails I do not
care.
Thus, using $next to signal "404 Not Found" is bad for many reasons:
1. 404 is one error of many, e.g. what about routing related errors like
"405 Method Not Allowed" and "415 Unsupported Media Type"?
2. What kind of *final handler* do I need to dispatch middlewares? For
router middlewares I probably want a *NotFoundHandler*, but for a
controller action I probably want a handler which returns a plain response
object.
3. Because of 2., you need some conventions, i.e. framework specific
conventions(!), which means it would neither be possible to reuse your
'/api/' middleware stack across multiple frameworks nor and more
importantly your RouteMiddleware itself.
> And by the way this is a bit what Slim and IIRC Zend Expressive do: route
> handlers can be controllers or can be pipes, that's how you can add "route
> middlewares" (I hope I'm not wrong here).
>
Slim controller actions
<https://www.slimframework.com/docs/concepts/middleware.html#how-do-i-add-middleware>
are
not middlewares, they get an $args argument instead of a $next.
Zend Expressive and Zend Stratigility:
$app->pipe('/', function (ServerRequestInterface $request, DelegateInterface
$delegate) {
return $delegate->process($request);
});
$app->pipe('/', function (ServerRequestInterface $request, DelegateInterface
$delegate) {
$response = new Response();
$response->getBody()->write('Wtf?');
return $response;
});
Zend Expressive is based on Stratigility and returns a 404 for '/'.
Interestingly, Zend Stratigility itself returns a 200 (content: 'Wtf?') –
yes, exactly the same code snippet can be used in both frameworks.
IMO, these setups are hard to debug, and to me, it is another reason why I
dislike routers/controllers which call $next: I can never be sure what
$next will return (without further knowledge about the framework).
--
You received this message because you are subscribed to the Google Groups "PHP
Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/php-fig/9fb17b11-95da-4b42-9737-e4464b5c090f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.