Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Support route-specific middleware pipeline via configuration? #190

Closed
michaelmoussa opened this issue Nov 19, 2015 · 4 comments · Fixed by #192
Closed

Support route-specific middleware pipeline via configuration? #190

michaelmoussa opened this issue Nov 19, 2015 · 4 comments · Fixed by #192

Comments

@michaelmoussa
Copy link
Contributor

When defining routes, we can specify the middleware to be executed in the configuration:

return [
    'routes' => [
        [
            'name' => 'foo',
            'path' => '/foo/{id}',
            'middleware' => FooMiddleware::class,
            'allowed_methods' => ['GET'],
        ]
    ]
];

I have a use case where I'd like to service a route by chaining a few different middlewares. They are application-specific middlewares that are shareable among resources (think user input validation, entity retrieval, and things of that nature), but I can only specify a single middleware in this configuration. I considered using the pre_routing and post_routing configuration pipelines, but they execute too early or too late, respectively, and I only need them to execute for this specific route, not for every request.

I managed to implement what I wanted by having my FooMiddleware actually be a middleware pipe:

class FooMiddlewareFactory
{
    public function __invoke(ContainerInterface $container)
    {
        $middleware = new MiddlewarePipe();
        $middleware->pipe($container->get(SomeMiddleware::class));
        $middleware->pipe($container->get(SomeOtherMiddleware::class));
        $middleware->pipe($container->get(YetAnotherMiddleware::class));

        return $middleware;
    }
}

Since a MiddlewarePipe is itself middleware, Expressive will accept it as the target middleware for this route, and execute the middlewares in the proper sequence.

However, it'd be much more convenient to be able to create this pipeline in the configuration rather than needing to create a factory to do it programmatically:

return [
    'routes' => [
        [
            'name' => 'foo',
            'path' => '/foo/{id}',
            'middleware' => [
                SomeMiddleware::class,
                SomeOtherMiddleware::class,
                YetAnotherMiddleware::class,
            ],
            'allowed_methods' => ['GET'],
        ]
    ]
];

This is currently not allowed because the value of middleware must be callable.

  1. Is there a better way to do what I'm trying to do already via configuration?
  2. Is the inability to create route-specific pipelines like above via configuration an oversight, or intentional?
  3. If it's an oversight, would you accept a backwards-compatible patch to get this into 1.0.0?
@weierophinney
Copy link
Member

@michaelmoussa Funny — I raised the specter of this in a comment on a previous issue:

I like the idea of the array notation, though we'll have to likely find a way to differentiate between that and a callable. I'll do some thinking on that in the coming days.

@michaelmoussa
Copy link
Contributor Author

Thanks @weierophinney. I had a couple of ideas in mind already, so since it seems you're open to it, I'll submit something and see if it'll work for you.

@weierophinney
Copy link
Member

@michaelmoussa Awesome; thanks!

@danizord
Copy link
Contributor

Could be middleware and middlewares?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants