mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-27 16:26:37 +03:00
Improved CrossDomainMiddleware preventing headers to be injected on non-CORS requests
This commit is contained in:
parent
0daa24739d
commit
839329d627
4 changed files with 49 additions and 16 deletions
|
@ -34,7 +34,7 @@ abstract class AbstractRestMiddleware implements MiddlewareInterface
|
||||||
*/
|
*/
|
||||||
public function __invoke(Request $request, Response $response, callable $out = null)
|
public function __invoke(Request $request, Response $response, callable $out = null)
|
||||||
{
|
{
|
||||||
if (strtolower($request->getMethod()) === 'options') {
|
if ($request->getMethod() === 'OPTIONS') {
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ class CheckAuthenticationMiddleware implements MiddlewareInterface
|
||||||
/** @var RouteResult $routeResult */
|
/** @var RouteResult $routeResult */
|
||||||
$routeResult = $request->getAttribute(RouteResult::class);
|
$routeResult = $request->getAttribute(RouteResult::class);
|
||||||
if ((isset($routeResult) && $routeResult->getMatchedRouteName() === 'rest-authenticate')
|
if ((isset($routeResult) && $routeResult->getMatchedRouteName() === 'rest-authenticate')
|
||||||
|| strtolower($request->getMethod()) === 'options'
|
|| $request->getMethod() === 'OPTIONS'
|
||||||
) {
|
) {
|
||||||
return $out($request, $response);
|
return $out($request, $response);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,17 +36,26 @@ class CrossDomainMiddleware implements MiddlewareInterface
|
||||||
{
|
{
|
||||||
/** @var Response $response */
|
/** @var Response $response */
|
||||||
$response = $out($request, $response);
|
$response = $out($request, $response);
|
||||||
|
if (! $request->hasHeader('Origin')) {
|
||||||
if (strtolower($request->getMethod()) === 'options') {
|
return $response;
|
||||||
$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')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,15 +21,37 @@ class CrossDomainMiddlewareTest extends TestCase
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
public function anyRequestIncludesTheAllowAccessHeader()
|
public function nonCrossDomainRequestsAreNotAffected()
|
||||||
{
|
{
|
||||||
|
$originalResponse = new Response();
|
||||||
$response = $this->middleware->__invoke(
|
$response = $this->middleware->__invoke(
|
||||||
ServerRequestFactory::fromGlobals(),
|
ServerRequestFactory::fromGlobals(),
|
||||||
new Response(),
|
$originalResponse,
|
||||||
function ($req, $resp) {
|
function ($req, $resp) {
|
||||||
return $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();
|
$headers = $response->getHeaders();
|
||||||
$this->assertArrayHasKey('Access-Control-Allow-Origin', $headers);
|
$this->assertArrayHasKey('Access-Control-Allow-Origin', $headers);
|
||||||
|
@ -41,11 +63,13 @@ class CrossDomainMiddlewareTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function optionsRequestIncludesMoreHeaders()
|
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;
|
return $resp;
|
||||||
});
|
});
|
||||||
|
$this->assertNotSame($originalResponse, $response);
|
||||||
|
|
||||||
$headers = $response->getHeaders();
|
$headers = $response->getHeaders();
|
||||||
$this->assertArrayHasKey('Access-Control-Allow-Origin', $headers);
|
$this->assertArrayHasKey('Access-Control-Allow-Origin', $headers);
|
||||||
|
|
Loading…
Reference in a new issue