diff --git a/module/Rest/src/Action/AbstractRestMiddleware.php b/module/Rest/src/Action/AbstractRestMiddleware.php index 9ef870f4..a273d248 100644 --- a/module/Rest/src/Action/AbstractRestMiddleware.php +++ b/module/Rest/src/Action/AbstractRestMiddleware.php @@ -34,7 +34,7 @@ abstract class AbstractRestMiddleware implements MiddlewareInterface */ public function __invoke(Request $request, Response $response, callable $out = null) { - if (strtolower($request->getMethod()) === 'options') { + if ($request->getMethod() === 'OPTIONS') { return $response; } diff --git a/module/Rest/src/Middleware/CheckAuthenticationMiddleware.php b/module/Rest/src/Middleware/CheckAuthenticationMiddleware.php index 0de25f8f..2910aad8 100644 --- a/module/Rest/src/Middleware/CheckAuthenticationMiddleware.php +++ b/module/Rest/src/Middleware/CheckAuthenticationMiddleware.php @@ -63,7 +63,7 @@ class CheckAuthenticationMiddleware implements MiddlewareInterface /** @var RouteResult $routeResult */ $routeResult = $request->getAttribute(RouteResult::class); if ((isset($routeResult) && $routeResult->getMatchedRouteName() === 'rest-authenticate') - || strtolower($request->getMethod()) === 'options' + || $request->getMethod() === 'OPTIONS' ) { return $out($request, $response); } diff --git a/module/Rest/src/Middleware/CrossDomainMiddleware.php b/module/Rest/src/Middleware/CrossDomainMiddleware.php index ed3d333e..4fba6944 100644 --- a/module/Rest/src/Middleware/CrossDomainMiddleware.php +++ b/module/Rest/src/Middleware/CrossDomainMiddleware.php @@ -36,17 +36,26 @@ class CrossDomainMiddleware implements MiddlewareInterface { /** @var Response $response */ $response = $out($request, $response); - - if (strtolower($request->getMethod()) === 'options') { - $response = $response->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') - ->withHeader('Access-Control-Max-Age', '1000') - ->withHeader( - // Allow all requested headers - 'Access-Control-Allow-Headers', - $request->getHeaderLine('Access-Control-Request-Headers') - ); + if (! $request->hasHeader('Origin')) { + return $response; } - return $response->withHeader('Access-Control-Allow-Origin', '*'); + // Add Allow-Origin header + $response = $response->withHeader('Access-Control-Allow-Origin', '*'); + if ($request->getMethod() !== 'OPTIONS') { + return $response; + } + + // Add OPTIONS-specific headers + $headers = [ + 'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, OPTIONS', // TODO Should be based on path + 'Access-Control-Max-Age' => '1000', + 'Access-Control-Allow-Headers' => $request->getHeaderLine('Access-Control-Request-Headers'), + ]; + foreach ($headers as $key => $value) { + $response = $response->withHeader($key, $value); + } + + return $response; } } diff --git a/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php b/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php index 92656c82..780de834 100644 --- a/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php +++ b/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php @@ -21,15 +21,37 @@ class CrossDomainMiddlewareTest extends TestCase /** * @test */ - public function anyRequestIncludesTheAllowAccessHeader() + public function nonCrossDomainRequestsAreNotAffected() { + $originalResponse = new Response(); $response = $this->middleware->__invoke( ServerRequestFactory::fromGlobals(), - new Response(), + $originalResponse, function ($req, $resp) { return $resp; } ); + $this->assertSame($originalResponse, $response); + + $headers = $response->getHeaders(); + $this->assertArrayNotHasKey('Access-Control-Allow-Origin', $headers); + $this->assertArrayNotHasKey('Access-Control-Allow-Headers', $headers); + } + + /** + * @test + */ + public function anyRequestIncludesTheAllowAccessHeader() + { + $originalResponse = new Response(); + $response = $this->middleware->__invoke( + ServerRequestFactory::fromGlobals()->withHeader('Origin', 'local'), + $originalResponse, + function ($req, $resp) { + return $resp; + } + ); + $this->assertNotSame($originalResponse, $response); $headers = $response->getHeaders(); $this->assertArrayHasKey('Access-Control-Allow-Origin', $headers); @@ -41,11 +63,13 @@ class CrossDomainMiddlewareTest extends TestCase */ public function optionsRequestIncludesMoreHeaders() { - $request = ServerRequestFactory::fromGlobals(['REQUEST_METHOD' => 'OPTIONS']); + $originalResponse = new Response(); + $request = ServerRequestFactory::fromGlobals(['REQUEST_METHOD' => 'OPTIONS'])->withHeader('Origin', 'local'); - $response = $this->middleware->__invoke($request, new Response(), function ($req, $resp) { + $response = $this->middleware->__invoke($request, $originalResponse, function ($req, $resp) { return $resp; }); + $this->assertNotSame($originalResponse, $response); $headers = $response->getHeaders(); $this->assertArrayHasKey('Access-Control-Allow-Origin', $headers);