CrossDomainMiddleware.php 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. <?php
  2. declare(strict_types=1);
  3. namespace Shlinkio\Shlink\Rest\Middleware;
  4. use Fig\Http\Message\RequestMethodInterface;
  5. use Mezzio\Router\RouteResult;
  6. use Psr\Http\Message\ResponseInterface;
  7. use Psr\Http\Message\ServerRequestInterface;
  8. use Psr\Http\Server\MiddlewareInterface;
  9. use Psr\Http\Server\RequestHandlerInterface;
  10. use Shlinkio\Shlink\Rest\Authentication;
  11. use function implode;
  12. class CrossDomainMiddleware implements MiddlewareInterface, RequestMethodInterface
  13. {
  14. public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
  15. {
  16. $response = $handler->handle($request);
  17. if (! $request->hasHeader('Origin')) {
  18. return $response;
  19. }
  20. // Add Allow-Origin header
  21. $response = $response->withHeader('Access-Control-Allow-Origin', $request->getHeader('Origin'))
  22. ->withHeader('Access-Control-Expose-Headers', implode(', ', [
  23. Authentication\Plugin\ApiKeyHeaderPlugin::HEADER_NAME,
  24. ]));
  25. if ($request->getMethod() !== self::METHOD_OPTIONS) {
  26. return $response;
  27. }
  28. return $this->addOptionsHeaders($request, $response);
  29. }
  30. private function addOptionsHeaders(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
  31. {
  32. /** @var RouteResult|null $matchedRoute */
  33. $matchedRoute = $request->getAttribute(RouteResult::class);
  34. $matchedMethods = $matchedRoute !== null ? $matchedRoute->getAllowedMethods() : [
  35. self::METHOD_GET,
  36. self::METHOD_POST,
  37. self::METHOD_PUT,
  38. self::METHOD_PATCH,
  39. self::METHOD_DELETE,
  40. self::METHOD_OPTIONS,
  41. ];
  42. $corsHeaders = [
  43. 'Access-Control-Allow-Methods' => implode(',', $matchedMethods),
  44. 'Access-Control-Max-Age' => '1000',
  45. 'Access-Control-Allow-Headers' => $request->getHeaderLine('Access-Control-Request-Headers'),
  46. ];
  47. foreach ($corsHeaders as $key => $value) {
  48. $response = $response->withHeader($key, $value);
  49. }
  50. return $response;
  51. }
  52. }