handle($request); if (! $request->hasHeader('Origin')) { return $response; } // Add Allow-Origin header $response = $response->withHeader('Access-Control-Allow-Origin', $request->getHeader('Origin')) ->withHeader('Access-Control-Expose-Headers', implode(', ', [ Authentication\Plugin\ApiKeyHeaderPlugin::HEADER_NAME, ])); if ($request->getMethod() !== self::METHOD_OPTIONS) { return $response; } return $this->addOptionsHeaders($request, $response); } private function addOptionsHeaders(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { /** @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-Max-Age' => '1000', 'Access-Control-Allow-Headers' => $request->getHeaderLine('Access-Control-Request-Headers'), ]; // Options requests should always be empty and have a 204 status code return EmptyResponse::withHeaders(array_merge($response->getHeaders(), $corsHeaders)); } }