mirror of
https://github.com/codeigniter4/CodeIgniter4.git
synced 2025-02-20 11:44:28 +08:00
fix: set headers for CORS (#9437)
Some checks failed
Deploy API Documentation / Deploy to api (push) Has been cancelled
Deploy User Guide (latest) / Deploy to gh-pages (push) Has been cancelled
AutoReview / Automatic Code Review (push) Has been cancelled
AutoReview / Check normalized composer.json (push) Has been cancelled
Coding Standards / PHP 8.1 Lint with PHP CS Fixer (push) Has been cancelled
Coding Standards / PHP 8.4 Lint with PHP CS Fixer (push) Has been cancelled
Deptrac / Architectural Inspection (push) Has been cancelled
Check File Permissions / Check File Permission (push) Has been cancelled
PHPCPD / phpcpd (push) Has been cancelled
PHPStan / PHP ${{ matrix.php-versions }} Static Analysis (push) Has been cancelled
PHPUnit / Setup PHP Version for Code Coverage (push) Has been cancelled
Psalm / Psalm Analysis (push) Has been cancelled
Rector / PHP 8.1 Analyze code (Rector) (push) Has been cancelled
Rector / PHP 8.4 Analyze code (Rector) (push) Has been cancelled
PHPUnit / Others (8.1) (push) Has been cancelled
PHPUnit / Others (8.2) (push) Has been cancelled
PHPUnit / Others (8.3) (push) Has been cancelled
PHPUnit / Others (8.4) (push) Has been cancelled
PHPUnit / DatabaseLive (MySQLi, 5.7, 8.1) (push) Has been cancelled
PHPUnit / DatabaseLive (MySQLi, 8.0, 8.1) (push) Has been cancelled
PHPUnit / DatabaseLive (MySQLi, 8.0, 8.2) (push) Has been cancelled
PHPUnit / DatabaseLive (MySQLi, 8.0, 8.3) (push) Has been cancelled
PHPUnit / DatabaseLive (MySQLi, 8.0, 8.4) (push) Has been cancelled
PHPUnit / DatabaseLive (OCI8, 8.0, 8.1) (push) Has been cancelled
PHPUnit / DatabaseLive (OCI8, 8.0, 8.2) (push) Has been cancelled
PHPUnit / DatabaseLive (OCI8, 8.0, 8.3) (push) Has been cancelled
PHPUnit / DatabaseLive (OCI8, 8.0, 8.4) (push) Has been cancelled
PHPUnit / DatabaseLive (Postgre, 8.0, 8.1) (push) Has been cancelled
PHPUnit / DatabaseLive (Postgre, 8.0, 8.2) (push) Has been cancelled
PHPUnit / DatabaseLive (Postgre, 8.0, 8.3) (push) Has been cancelled
PHPUnit / DatabaseLive (Postgre, 8.0, 8.4) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLSRV, 8.0, 8.1) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLSRV, 8.0, 8.2) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLSRV, 8.0, 8.3) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLSRV, 8.0, 8.4) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLite3, 8.0, 8.1) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLite3, 8.0, 8.2) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLite3, 8.0, 8.3) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLite3, 8.0, 8.4) (push) Has been cancelled
PHPUnit / SeparateProcess (8.1) (push) Has been cancelled
PHPUnit / SeparateProcess (8.2) (push) Has been cancelled
PHPUnit / SeparateProcess (8.3) (push) Has been cancelled
PHPUnit / SeparateProcess (8.4) (push) Has been cancelled
PHPUnit / CacheLive (8.1) (push) Has been cancelled
PHPUnit / CacheLive (8.2) (push) Has been cancelled
PHPUnit / CacheLive (8.3) (push) Has been cancelled
PHPUnit / CacheLive (8.4) (push) Has been cancelled
PHPUnit / Upload coverage results to Coveralls (push) Has been cancelled
Some checks failed
Deploy API Documentation / Deploy to api (push) Has been cancelled
Deploy User Guide (latest) / Deploy to gh-pages (push) Has been cancelled
AutoReview / Automatic Code Review (push) Has been cancelled
AutoReview / Check normalized composer.json (push) Has been cancelled
Coding Standards / PHP 8.1 Lint with PHP CS Fixer (push) Has been cancelled
Coding Standards / PHP 8.4 Lint with PHP CS Fixer (push) Has been cancelled
Deptrac / Architectural Inspection (push) Has been cancelled
Check File Permissions / Check File Permission (push) Has been cancelled
PHPCPD / phpcpd (push) Has been cancelled
PHPStan / PHP ${{ matrix.php-versions }} Static Analysis (push) Has been cancelled
PHPUnit / Setup PHP Version for Code Coverage (push) Has been cancelled
Psalm / Psalm Analysis (push) Has been cancelled
Rector / PHP 8.1 Analyze code (Rector) (push) Has been cancelled
Rector / PHP 8.4 Analyze code (Rector) (push) Has been cancelled
PHPUnit / Others (8.1) (push) Has been cancelled
PHPUnit / Others (8.2) (push) Has been cancelled
PHPUnit / Others (8.3) (push) Has been cancelled
PHPUnit / Others (8.4) (push) Has been cancelled
PHPUnit / DatabaseLive (MySQLi, 5.7, 8.1) (push) Has been cancelled
PHPUnit / DatabaseLive (MySQLi, 8.0, 8.1) (push) Has been cancelled
PHPUnit / DatabaseLive (MySQLi, 8.0, 8.2) (push) Has been cancelled
PHPUnit / DatabaseLive (MySQLi, 8.0, 8.3) (push) Has been cancelled
PHPUnit / DatabaseLive (MySQLi, 8.0, 8.4) (push) Has been cancelled
PHPUnit / DatabaseLive (OCI8, 8.0, 8.1) (push) Has been cancelled
PHPUnit / DatabaseLive (OCI8, 8.0, 8.2) (push) Has been cancelled
PHPUnit / DatabaseLive (OCI8, 8.0, 8.3) (push) Has been cancelled
PHPUnit / DatabaseLive (OCI8, 8.0, 8.4) (push) Has been cancelled
PHPUnit / DatabaseLive (Postgre, 8.0, 8.1) (push) Has been cancelled
PHPUnit / DatabaseLive (Postgre, 8.0, 8.2) (push) Has been cancelled
PHPUnit / DatabaseLive (Postgre, 8.0, 8.3) (push) Has been cancelled
PHPUnit / DatabaseLive (Postgre, 8.0, 8.4) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLSRV, 8.0, 8.1) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLSRV, 8.0, 8.2) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLSRV, 8.0, 8.3) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLSRV, 8.0, 8.4) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLite3, 8.0, 8.1) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLite3, 8.0, 8.2) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLite3, 8.0, 8.3) (push) Has been cancelled
PHPUnit / DatabaseLive (SQLite3, 8.0, 8.4) (push) Has been cancelled
PHPUnit / SeparateProcess (8.1) (push) Has been cancelled
PHPUnit / SeparateProcess (8.2) (push) Has been cancelled
PHPUnit / SeparateProcess (8.3) (push) Has been cancelled
PHPUnit / SeparateProcess (8.4) (push) Has been cancelled
PHPUnit / CacheLive (8.1) (push) Has been cancelled
PHPUnit / CacheLive (8.2) (push) Has been cancelled
PHPUnit / CacheLive (8.3) (push) Has been cancelled
PHPUnit / CacheLive (8.4) (push) Has been cancelled
PHPUnit / Upload coverage results to Coveralls (push) Has been cancelled
* fix: set everything in the before filter for CORS * fix append vary header * cors: apply response headers in the after filter only if they are not already set * cs fix
This commit is contained in:
parent
efcabb3fdf
commit
c430f34720
@ -58,22 +58,32 @@ class Cors implements FilterInterface
|
|||||||
|
|
||||||
$this->createCorsService($arguments);
|
$this->createCorsService($arguments);
|
||||||
|
|
||||||
if (! $this->cors->isPreflightRequest($request)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var ResponseInterface $response */
|
/** @var ResponseInterface $response */
|
||||||
$response = service('response');
|
$response = service('response');
|
||||||
|
|
||||||
$response = $this->cors->handlePreflightRequest($request, $response);
|
if ($this->cors->isPreflightRequest($request)) {
|
||||||
|
$response = $this->cors->handlePreflightRequest($request, $response);
|
||||||
|
|
||||||
// Always adds `Vary: Access-Control-Request-Method` header for cacheability.
|
// Always adds `Vary: Access-Control-Request-Method` header for cacheability.
|
||||||
// If there is an intermediate cache server such as a CDN, if a plain
|
// If there is an intermediate cache server such as a CDN, if a plain
|
||||||
// OPTIONS request is sent, it may be cached. But valid preflight requests
|
// OPTIONS request is sent, it may be cached. But valid preflight requests
|
||||||
// have this header, so it will be cached separately.
|
// have this header, so it will be cached separately.
|
||||||
$response->appendHeader('Vary', 'Access-Control-Request-Method');
|
$response->appendHeader('Vary', 'Access-Control-Request-Method');
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->is('OPTIONS')) {
|
||||||
|
// Always adds `Vary: Access-Control-Request-Method` header for cacheability.
|
||||||
|
// If there is an intermediate cache server such as a CDN, if a plain
|
||||||
|
// OPTIONS request is sent, it may be cached. But valid preflight requests
|
||||||
|
// have this header, so it will be cached separately.
|
||||||
|
$response->appendHeader('Vary', 'Access-Control-Request-Method');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->cors->addResponseHeaders($request, $response);
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,8 +97,6 @@ class Cors implements FilterInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param list<string>|null $arguments
|
* @param list<string>|null $arguments
|
||||||
*
|
|
||||||
* @return ResponseInterface|null
|
|
||||||
*/
|
*/
|
||||||
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
|
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
|
||||||
{
|
{
|
||||||
@ -98,6 +106,10 @@ class Cors implements FilterInterface
|
|||||||
|
|
||||||
$this->createCorsService($arguments);
|
$this->createCorsService($arguments);
|
||||||
|
|
||||||
|
if ($this->cors->hasResponseHeaders($request, $response)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Always adds `Vary: Access-Control-Request-Method` header for cacheability.
|
// Always adds `Vary: Access-Control-Request-Method` header for cacheability.
|
||||||
// If there is an intermediate cache server such as a CDN, if a plain
|
// If there is an intermediate cache server such as a CDN, if a plain
|
||||||
// OPTIONS request is sent, it may be cached. But valid preflight requests
|
// OPTIONS request is sent, it may be cached. But valid preflight requests
|
||||||
|
@ -227,4 +227,24 @@ class Cors
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if response headers were set
|
||||||
|
*/
|
||||||
|
public function hasResponseHeaders(RequestInterface $request, ResponseInterface $response): bool
|
||||||
|
{
|
||||||
|
if (! $response->hasHeader('Access-Control-Allow-Origin')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->config['supportsCredentials']
|
||||||
|
&& ! $response->hasHeader('Access-Control-Allow-Credentials')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ! ($this->config['exposedHeaders'] !== [] && (! $response->hasHeader('Access-Control-Expose-Headers') || ! str_contains(
|
||||||
|
$response->getHeaderLine('Access-Control-Expose-Headers'),
|
||||||
|
implode(', ', $this->config['exposedHeaders']),
|
||||||
|
)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ namespace CodeIgniter\Filters;
|
|||||||
use CodeIgniter\Exceptions\ConfigException;
|
use CodeIgniter\Exceptions\ConfigException;
|
||||||
use CodeIgniter\HTTP\CLIRequest;
|
use CodeIgniter\HTTP\CLIRequest;
|
||||||
use CodeIgniter\HTTP\IncomingRequest;
|
use CodeIgniter\HTTP\IncomingRequest;
|
||||||
|
use CodeIgniter\HTTP\RedirectResponse;
|
||||||
use CodeIgniter\HTTP\RequestInterface;
|
use CodeIgniter\HTTP\RequestInterface;
|
||||||
use CodeIgniter\HTTP\ResponseInterface;
|
use CodeIgniter\HTTP\ResponseInterface;
|
||||||
use CodeIgniter\HTTP\SiteURI;
|
use CodeIgniter\HTTP\SiteURI;
|
||||||
@ -154,6 +155,25 @@ final class CorsTest extends CIUnitTestCase
|
|||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function handleRedirect(RequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
$response = $this->cors->before($request);
|
||||||
|
if ($response instanceof ResponseInterface) {
|
||||||
|
$this->response = $response;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = service('redirectresponse');
|
||||||
|
|
||||||
|
$response = $this->cors->after($request, $response);
|
||||||
|
$response ??= service('redirectresponse');
|
||||||
|
|
||||||
|
$this->response = $response;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
public function testItDoesModifyOnARequestWithSameOrigin(): void
|
public function testItDoesModifyOnARequestWithSameOrigin(): void
|
||||||
{
|
{
|
||||||
$this->cors = $this->createCors(['allowedOrigins' => ['*']]);
|
$this->cors = $this->createCors(['allowedOrigins' => ['*']]);
|
||||||
@ -461,4 +481,29 @@ final class CorsTest extends CIUnitTestCase
|
|||||||
// Always adds `Vary: Access-Control-Request-Method` header.
|
// Always adds `Vary: Access-Control-Request-Method` header.
|
||||||
$this->assertHeader('Vary', 'Access-Control-Request-Method');
|
$this->assertHeader('Vary', 'Access-Control-Request-Method');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testItReturnsAllowOriginHeaderOnValidActualRequestWithRedirect(): void
|
||||||
|
{
|
||||||
|
$this->cors = $this->createCors();
|
||||||
|
$request = $this->createValidActualRequest();
|
||||||
|
|
||||||
|
$response = $this->handleRedirect($request);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(RedirectResponse::class, $response);
|
||||||
|
$this->assertTrue($response->hasHeader('Access-Control-Allow-Origin'));
|
||||||
|
$this->assertHeader('Access-Control-Allow-Origin', 'http://localhost');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItReturnsAllowOriginHeaderOnAllowAllOriginRequestWithRedirect(): void
|
||||||
|
{
|
||||||
|
$this->cors = $this->createCors(['allowedOrigins' => ['*']]);
|
||||||
|
$request = $this->createRequest();
|
||||||
|
$request->setHeader('Origin', 'http://localhost');
|
||||||
|
|
||||||
|
$response = $this->handleRedirect($request);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(RedirectResponse::class, $response);
|
||||||
|
$this->assertTrue($response->hasHeader('Access-Control-Allow-Origin'));
|
||||||
|
$this->assertHeader('Access-Control-Allow-Origin', '*');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -521,4 +521,41 @@ final class CorsTest extends CIUnitTestCase
|
|||||||
$response->hasHeader('Access-Control-Allow-Methods'),
|
$response->hasHeader('Access-Control-Allow-Methods'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testHasResponseHeadersFalse(): void
|
||||||
|
{
|
||||||
|
$config = $this->getDefaultConfig();
|
||||||
|
$config['allowedOrigins'] = ['http://localhost:8080'];
|
||||||
|
$config['allowedMethods'] = ['GET', 'POST', 'PUT'];
|
||||||
|
$cors = $this->createCors($config);
|
||||||
|
|
||||||
|
$request = $this->createRequest()
|
||||||
|
->withMethod('GET')
|
||||||
|
->setHeader('Origin', 'http://localhost:8080');
|
||||||
|
|
||||||
|
$response = service('redirectresponse', null, false);
|
||||||
|
|
||||||
|
$this->assertFalse(
|
||||||
|
$cors->hasResponseHeaders($request, $response),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHasResponseHeadersTrue(): void
|
||||||
|
{
|
||||||
|
$config = $this->getDefaultConfig();
|
||||||
|
$config['allowedOrigins'] = ['http://localhost:8080'];
|
||||||
|
$config['allowedMethods'] = ['GET', 'POST'];
|
||||||
|
$cors = $this->createCors($config);
|
||||||
|
|
||||||
|
$request = $this->createRequest()
|
||||||
|
->withMethod('GET')
|
||||||
|
->setHeader('Origin', 'http://localhost:8080');
|
||||||
|
|
||||||
|
$response = service('redirectresponse', null, false);
|
||||||
|
$response = $cors->addResponseHeaders($request, $response);
|
||||||
|
|
||||||
|
$this->assertTrue(
|
||||||
|
$cors->hasResponseHeaders($request, $response),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ Bugs Fixed
|
|||||||
**********
|
**********
|
||||||
|
|
||||||
- **CURLRequest:** Fixed an issue where multiple header sections appeared in the CURL response body during multiple redirects from the target server.
|
- **CURLRequest:** Fixed an issue where multiple header sections appeared in the CURL response body during multiple redirects from the target server.
|
||||||
|
- **Cors:** Fixed a bug in the Cors filter that caused the appropriate headers to not be added when another filter returned a response object in the ``before`` filter.
|
||||||
|
|
||||||
See the repo's
|
See the repo's
|
||||||
`CHANGELOG.md <https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHANGELOG.md>`_
|
`CHANGELOG.md <https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHANGELOG.md>`_
|
||||||
|
Loading…
x
Reference in New Issue
Block a user