cors-middleware
cors-middleware copied to clipboard
Provide an example for dynamically specifying allowed methods for Slim 4
I've trouble dynamically specifying the allowed methods while using Slim4 like you did in the readme file for Slim3
use Fastroute\Dispatcher;
use Tuupola\Middleware\CorsMiddleware;
$app->add(
new CorsMiddleware([
"origin" => ["*"],
"methods" => function($request) use ($app) {
$container = $app->getContainer();
$dispatch = $container["router"]->dispatch($request);
if (Dispatcher::METHOD_NOT_ALLOWED === $dispatch[0]) {
return $dispatch[1];
}
}
])
);
I've tried the following for Slim 4:
$app->addMiddleware(new Tuupola\Middleware\CorsMiddleware([
'methods' => function ($request): array {
$routeContext = RouteContext::fromRequest($request);
$routingResults = $routeContext->getRoutingResults();
$methods = $routingResults->getAllowedMethods();
return $methods;
},
]));
But either when I put $app->addRoutingMiddleware(); in front of the code block above I get the following error:
PHP Fatal error: Uncaught RuntimeException: Cannot create RouteContext before routing has been completed in /var/www/html/vendor/slim/slim/Slim/Routing/RouteContext.php:40
Stack trace:
#0 /var/www/html/public/index.php(103): Slim\\Routing\\RouteContext::fromRequest()
#1 /var/www/html/vendor/tuupola/cors-middleware/src/CorsMiddleware.php(175): Closure->{closure}()
#2 /var/www/html/vendor/tuupola/cors-middleware/src/CorsMiddleware.php(91): Tuupola\\Middleware\\CorsMiddleware->buildSettings()
#3 /var/www/html/vendor/slim/slim/Slim/MiddlewareDispatcher.php(147): Tuupola\\Middleware\\CorsMiddleware->process()
#4 /var/www/html/vendor/slim/slim/Slim/MiddlewareDispatcher.php(81): Psr\\Http\\Server\\RequestHandlerInterface@anonymous->handle()
#5 /var/www/html/vendor/slim/slim/Slim/App.php(215): Slim\\MiddlewareDispatcher->handle()
#6 /var/www/html/vendor/slim/slim/Slim/App.php(199): Slim\\App->handle()
#7 /var/www/html/public/index.php(127): Slim\\App->run()
#8 {main}
thrown in /var/www/html/vendor/slim/slim/Slim/Routing/RouteContext.php on line 40
or when I put $app->addRoutingMiddleware(); after the code block, the Cors middleware doesn't get invoked.
I can mitigate the first error where it complains about the RouteContext when I implement a OPTIONS catch-all block like so:
$app->options('/{routes:.+}', function (ServerRequestInterface $request, ResponseInterface $response, $args): ResponseInterface {
return $response;
});
But I wonder if I can get rid of the OPTIONS catch-all block altogether, what I'm missing here?
I am not sure if I have ever used that feature with Slim 4. Most API projects I have are still Slim 3. I try to find if I have example somewhere. I just remember there has never been easy way to get that info.
I have the same problem, some idea?
same 👍🏻
It works for me with the following config:
// init container
// ...
// init middleware
$app->options('/{routes:.+}', fn ($request, $response, $args) => $response);
$app->add(new CorsMiddleware([
'logger' => $container->getLogger(),
'origin' => array_merge(['http://localhost'], Settings::get('api.custom_safe_hosts')),
'methods' => function (ServerRequest $request): array {
$routeContext = RouteContext::fromRequest($request);
$routingResults = $routeContext->getRoutingResults();
return $routingResults->getAllowedMethods();
},
'headers.allow' => ['Authorization', 'If-Match', 'If-Unmodified-Since'],
'headers.expose' => ['Authorization', 'Etag'],
'credentials' => true,
'cache' => 60,
'error' => function (ServerRequest $request, \Slim\Psr7\Response $response, array $arguments) {
$arguments['origin'] = $_SERVER['HTTP_ORIGIN'];
return $response
->withHeader('Content-Type', 'application/json')
->withBody((new StreamFactory())->createStream(json_encode($arguments, \JSON_UNESCAPED_SLASHES | \JSON_PRETTY_PRINT)));
},
]));
// init rest of middleware, including routing middleware
$app->run();
So apparently the OPTIONS catch-all block is really needed, as stated on https://www.slimframework.com/docs/v4/cookbook/enable-cors.html