-
Notifications
You must be signed in to change notification settings - Fork 196
Added support for route-specific middleware pipe via configuration #192
Changes from 7 commits
e9e0b9a
a43c889
a5c0c23
12d4e14
bdd7ec7
3ecc821
d574ca7
105f8c3
95b15f7
f3eb327
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -343,7 +343,19 @@ public function routeMiddleware(ServerRequestInterface $request, ResponseInterfa | |
return $middleware($request, $response, $next); | ||
} | ||
|
||
if (! is_string($middleware)) { | ||
if (is_array($middleware)) { | ||
$middlewarePipe = new MiddlewarePipe(); | ||
|
||
foreach ($middleware as $middlewareItem) { | ||
$middlewarePipe->pipe( | ||
is_callable($middlewareItem) ? $middlewareItem : $this->marshalMiddleware($middlewareItem) | ||
); | ||
} | ||
|
||
return $middlewarePipe; | ||
} | ||
|
||
if (!is_string($middleware)) { | ||
throw new Exception\InvalidMiddlewareException( | ||
'The middleware specified is not callable' | ||
); | ||
|
@@ -377,7 +389,7 @@ public function routeMiddleware(ServerRequestInterface $request, ResponseInterfa | |
* pipeline. | ||
* | ||
* @param string|Router\Route $path | ||
* @param callable|string $middleware Middleware (or middleware service name) to associate with route. | ||
* @param callable|string|array $middleware Middleware (or middleware service name) to associate with route. | ||
* @param null|array $methods HTTP method to accept; null indicates any. | ||
* @param null|string $name the name of the route | ||
* @return Router\Route | ||
|
@@ -531,6 +543,36 @@ private function checkForDuplicateRoute($path, $methods = null) | |
} | ||
} | ||
|
||
/** | ||
* Attempts to retrieve middleware from the container, or instantiate it directly. | ||
* | ||
* @param string $middleware | ||
* | ||
* @return array | ||
* @throws Exception\InvalidMiddlewareException If unable to obtain callable middleware | ||
*/ | ||
private function marshalMiddleware($middleware) | ||
{ | ||
$callable = $this->marshalMiddlewareFromContainer($middleware); | ||
|
||
if (is_callable($callable)) { | ||
return $callable; | ||
} | ||
|
||
$callable = $this->marshalInvokableMiddleware($middleware); | ||
|
||
if (is_callable($callable)) { | ||
return $callable; | ||
} else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for |
||
throw new Exception\InvalidMiddlewareException( | ||
sprintf( | ||
'Unable to resolve middleware "%s" to a callable', | ||
$middleware | ||
) | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* Attempt to retrieve the given middleware from the container. | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
use Zend\Expressive\Router\FastRouteRouter; | ||
use Zend\Expressive\Router\Route; | ||
use Zend\Expressive\Router\RouterInterface; | ||
use Zend\Stratigility\MiddlewarePipe; | ||
|
||
/** | ||
* Factory to use with an IoC container in order to return an Application instance. | ||
|
@@ -175,8 +176,10 @@ private function injectRoutes(Application $app, ContainerInterface $container) | |
} else { | ||
$methods = Route::HTTP_METHOD_ANY; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reviewing this, I wonder if it might make sense to do a "container-aware middleware pipe" which would lazy-load the middleware only when calling it. Looking into the Stratigility codebase, this would require both an alternate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @michaelmoussa In reviewing this for merge... I think the code above is in the wrong place! Everywhere else, we delay fetching from the container unless we're dispatching the middleware. As such, I think this needs to be moved to However, for that to happen, a few other changes are necessary:
The above bit that creates a middleware pipe would then move into If you go that route, you could likely move the bits from So, now the question: do you want to tackle those changes, or do you want me to do a PR against your branch? This approach would mean we don't have to worry about changes to Stratigility (as I think it's fine to fetch all the middleware for a given There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @weierophinney Makes sense. Why go through the effort of potentially expensive middleware retrievals from the container if you don't even know if those middlewares will be used in this request? I think 3ecc821 takes care of this in the way you had in mind. If not, hopefully it's a good start. Let me know if I understood correctly and/or if this needs additional polish. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @weierophinney I noticed that the changes thus far would not (yet) allow this type of array configuration in the pre- and post-routing pipelines. Of course, one could just specify them separately, like this: return [
'middleware_pipeline' => [
'pre_routing' => [
[
'middleware' => 'Foo',
'path' => '/foobar',
],
[
'middleware' => 'Bar',
'path' => '/foobar',
],
[
'middleware' => 'Foobar',
'path' => '/foobar',
],
],
],
]; but something like this would be much more concise and potentially easier to read: return [
'middleware_pipeline' => [
'pre_routing' => [
[
'middleware' => [
'Foo',
'Bar',
'FooBar'
],
'path' => '/foobar',
],
],
],
]; Do you agree? Would you want to try to cram that into this PR as well or do it as a future PR hopefully still targeting 1.0.0? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interestingly, this comment doesn't show on the website; I think because Yes, I think we should add this into the current pull request, as it makes On Tue, Nov 24, 2015 at 11:28 PM, Michael Moussa notifications@github.com
Matthew Weier O'Phinney |
||
$name = isset($spec['name']) ? $spec['name'] : null; | ||
$route = new Route($spec['path'], $spec['middleware'], $methods, $name); | ||
|
||
$name = isset($spec['name']) ? $spec['name'] : null; | ||
|
||
$route = new Route($spec['path'], $spec['middleware'], $methods, $name); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change can be reverted? |
||
|
||
if (isset($spec['options'])) { | ||
$options = $spec['options']; | ||
|
@@ -209,12 +212,17 @@ private function injectMiddleware(array $collection, Application $app, Container | |
continue; | ||
} | ||
|
||
$path = isset($spec['path']) ? $spec['path'] : '/'; | ||
$middleware = $spec['middleware']; | ||
$error = array_key_exists('error', $spec) ? (bool) $spec['error'] : false; | ||
$pipe = $error ? 'pipeErrorHandler' : 'pipe'; | ||
$path = isset($spec['path']) ? $spec['path'] : '/'; | ||
$error = array_key_exists('error', $spec) ? (bool) $spec['error'] : false; | ||
$pipe = $error ? 'pipeErrorHandler' : 'pipe'; | ||
|
||
$app->{$pipe}($path, $middleware); | ||
if (is_array($spec['middleware'])) { | ||
foreach ($spec['middleware'] as $middleware) { | ||
$app->{$pipe}($path, $middleware); | ||
} | ||
} else { | ||
$app->{$pipe}($path, $spec['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.