Fixed CrossDomainMiddleware not inferring proper allowed methods

This commit is contained in:
Alejandro Celaya
2021-01-24 13:49:57 +01:00
parent ef54caab85
commit f585cfe02e
3 changed files with 32 additions and 36 deletions

View File

@@ -6,7 +6,6 @@ namespace Shlinkio\Shlink\Rest\Middleware;
use Fig\Http\Message\RequestMethodInterface;
use Laminas\Diactoros\Response\EmptyResponse;
use Mezzio\Router\RouteResult;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
@@ -42,20 +41,8 @@ class CrossDomainMiddleware implements MiddlewareInterface, RequestMethodInterfa
private function addOptionsHeaders(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
// TODO This won't work. The route has to be matched from the router as this middleware needs to be executed
// before trying to match the route
/** @var RouteResult|null $matchedRoute */
$matchedRoute = $request->getAttribute(RouteResult::class);
$matchedMethods = $matchedRoute !== null ? $matchedRoute->getAllowedMethods() : [
self::METHOD_GET,
self::METHOD_POST,
self::METHOD_PUT,
self::METHOD_PATCH,
self::METHOD_DELETE,
self::METHOD_OPTIONS,
];
$corsHeaders = [
'Access-Control-Allow-Methods' => implode(',', $matchedMethods),
'Access-Control-Allow-Methods' => $this->resolveCorsAllowedMethods($response),
'Access-Control-Allow-Headers' => $request->getHeaderLine('Access-Control-Request-Headers'),
'Access-Control-Max-Age' => $this->config['max_age'],
];
@@ -63,4 +50,22 @@ class CrossDomainMiddleware implements MiddlewareInterface, RequestMethodInterfa
// Options requests should always be empty and have a 204 status code
return EmptyResponse::withHeaders(array_merge($response->getHeaders(), $corsHeaders));
}
private function resolveCorsAllowedMethods(ResponseInterface $response): string
{
// ImplicitOptionsMiddleware resolves allowed methods using the RouteResult request's attribute and sets them
// in the "Allow" header.
// If the header is there, we can re-use the value as it is.
if ($response->hasHeader('Allow')) {
return $response->getHeaderLine('Allow');
}
return implode(',', [
self::METHOD_GET,
self::METHOD_POST,
self::METHOD_PUT,
self::METHOD_PATCH,
self::METHOD_DELETE,
]);
}
}