Improved CrossDomainMiddleware preventing headers to be injected on non-CORS requests

This commit is contained in:
Alejandro Celaya 2016-07-19 20:20:18 +02:00
parent 0daa24739d
commit 839329d627
4 changed files with 49 additions and 16 deletions

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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);