Skip to content
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

Provide an example for dynamically specifying allowed methods for Slim 4 #54

Open
jk opened this issue Nov 10, 2021 · 4 comments
Open
Assignees

Comments

@jk
Copy link

jk commented Nov 10, 2021

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?

@tuupola
Copy link
Owner

tuupola commented Nov 10, 2021

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.

@tuupola tuupola self-assigned this Jan 7, 2022
@GoldraK
Copy link

GoldraK commented Mar 15, 2022

I have the same problem, some idea?

@killua-eu
Copy link

same 👍🏻

@mbolli
Copy link

mbolli commented Jul 14, 2022

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

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

No branches or pull requests

5 participants