-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 68f52f2
Showing
4 changed files
with
479 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Effectra/cors | ||
|
||
Effectra/cors is a PHP package that provides middleware and service classes for handling Cross-Origin Resource Sharing (CORS) in web applications. CORS is a security feature implemented by web browsers to control access to resources on a different origin. | ||
|
||
## Installation | ||
|
||
You can install the Effectra/cors package via Composer: | ||
|
||
```bash | ||
composer require effectra/cors | ||
``` | ||
|
||
## Usage | ||
|
||
### CorsMiddleware | ||
|
||
The `CorsMiddleware` class is a PSR-15 middleware that can be used in a middleware stack to handle CORS requests. It checks incoming requests for CORS-related headers and adds appropriate headers to the response. | ||
|
||
#### Example: | ||
|
||
```php | ||
use Effectra\Cors\CorsMiddleware; | ||
use Effectra\Cors\CorsService; | ||
use Psr\Http\Server\MiddlewareInterface; | ||
|
||
// Create a CorsService instance with desired configuration | ||
$corsService = new CorsService([ | ||
'allowedOrigins' => ['https://example.com'], | ||
'allowedMethods' => ['GET', 'POST'], | ||
'allowedHeaders' => ['Content-Type'], | ||
]); | ||
|
||
// Create the CorsMiddleware instance | ||
$corsMiddleware = new CorsMiddleware($corsService, ['/api']); | ||
|
||
// Add the middleware to your middleware stack | ||
$middlewareStack = [ | ||
// Other middleware... | ||
$corsMiddleware, | ||
// Other middleware... | ||
]; | ||
``` | ||
|
||
### CorsService | ||
|
||
The `CorsService` class provides the core functionality for handling CORS requests. It allows you to configure various CORS-related settings. | ||
|
||
#### Example: | ||
|
||
```php | ||
use Effectra\Cors\CorsService; | ||
|
||
// Create a CorsService instance with desired configuration | ||
$corsService = new CorsService([ | ||
'allowedOrigins' => ['https://example.com'], | ||
'allowedMethods' => ['GET', 'POST'], | ||
'allowedHeaders' => ['Content-Type'], | ||
]); | ||
|
||
// Check if a request is a CORS request | ||
$isCorsRequest = $corsService->isCorsRequest($request); | ||
|
||
// Check if a request is a preflight request | ||
$isPreflightRequest = $corsService->isPreflightRequest($request); | ||
|
||
// Handle a preflight request and add necessary headers to the response | ||
$preflightResponse = $corsService->handlePreflightRequest($request); | ||
|
||
// Check if a specific origin is allowed | ||
$isOriginAllowed = $corsService->isOriginAllowed($request); | ||
|
||
// Add CORS headers to the actual response | ||
$actualResponse = $corsService->addActualRequestHeaders($response, $request); | ||
``` | ||
|
||
## Configuration | ||
|
||
The `CorsService` class allows you to configure various CORS-related settings using an options array. | ||
|
||
### Available Options: | ||
|
||
- `allowedOrigins`: An array of allowed origins. | ||
- `allowedOriginsPatterns`: An array of allowed origin patterns (wildcards). | ||
- `allowedMethods`: An array of allowed HTTP methods. | ||
- `allowedHeaders`: An array of allowed headers. | ||
- `supportsCredentials`: Whether credentials (cookies, HTTP authentication) should be supported. | ||
- `maxAge`: Maximum time (in seconds) that the results of a preflight request can be cached. | ||
- `exposedHeaders`: An array of headers exposed to the response. | ||
|
||
## Contributing | ||
|
||
If you'd like to contribute to this project, please follow our [contribution guidelines](CONTRIBUTING.md). | ||
|
||
## License | ||
|
||
The Effectra/cors package is open-sourced software licensed under the [MIT license](LICENSE). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"name": "effectra/cors", | ||
"description": "PHP library for enabling CORS (Cross-Origin Resource Sharing) in HTTP requests/responses. It follows PSR guidelines, and can be easily integrated into PHP projects.", | ||
"type": "library", | ||
"license": "MIT", | ||
"autoload": { | ||
"psr-4": { | ||
"Effectra\\Cors\\": "src/" | ||
} | ||
}, | ||
"authors": [ | ||
{ | ||
"name": "Mohammed Taha", | ||
"email": "info@mohammedtaha.net" | ||
} | ||
], | ||
"require": { | ||
"psr/http-message": "^2.0@dev", | ||
"psr/http-server-handler": "^1.0@dev", | ||
"psr/http-server-middleware": "^1.0@dev" | ||
}, | ||
"minimum-stability": "stable" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
<?php | ||
|
||
namespace Effectra\Cors; | ||
|
||
use Psr\Http\Message\ServerRequestInterface; | ||
use Psr\Http\Message\ResponseInterface; | ||
use Psr\Http\Server\MiddlewareInterface; | ||
use Psr\Http\Server\RequestHandlerInterface; | ||
|
||
class CorsMiddleware implements MiddlewareInterface | ||
{ | ||
/** @var CorsService $cors */ | ||
protected $cors; | ||
|
||
|
||
protected array $paths = []; | ||
|
||
public function __construct(CorsService $cors, array $paths = []) | ||
{ | ||
$this->cors = $cors; | ||
$this->paths = $paths; | ||
} | ||
|
||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface | ||
{ | ||
// Check if we're dealing with CORS and if we should handle it | ||
if (!$this->shouldRun($request)) { | ||
return $handler->handle($request); | ||
} | ||
|
||
// For Preflight, return the Preflight response | ||
if ($this->cors->isPreflightRequest($request)) { | ||
$response = $this->cors->handlePreflightRequest($request); | ||
|
||
$this->cors->varyHeader($response, 'Access-Control-Request-Method'); | ||
|
||
return $response; | ||
} | ||
|
||
// Handle the request | ||
$response = $handler->handle($request); | ||
|
||
if ($request->getMethod() === 'OPTIONS') { | ||
$this->cors->varyHeader($response, 'Access-Control-Request-Method'); | ||
} | ||
|
||
return $this->addHeaders($request, $response); | ||
} | ||
|
||
/** | ||
* Add the headers to the Response, if they don't exist yet. | ||
* | ||
* @param ServerRequestInterface $request | ||
* @param ResponseInterface $response | ||
* @return ResponseInterface | ||
*/ | ||
protected function addHeaders(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface | ||
{ | ||
if (!$response->hasHeader('Access-Control-Allow-Origin')) { | ||
// Add the CORS headers to the Response | ||
$response = $this->cors->addActualRequestHeaders($response, $request); | ||
} | ||
|
||
return $response; | ||
} | ||
|
||
/** | ||
* Determine if the request has a URI that should pass through the CORS flow. | ||
* | ||
* @param ServerRequestInterface $request | ||
* @return bool | ||
*/ | ||
protected function shouldRun(ServerRequestInterface $request): bool | ||
{ | ||
return $this->isMatchingPath($request); | ||
} | ||
|
||
/** | ||
* The path from the config, to see if the CORS Service should run | ||
* | ||
* @param ServerRequestInterface $request | ||
* @return bool | ||
*/ | ||
protected function isMatchingPath(ServerRequestInterface $request): bool | ||
{ | ||
// Get the paths from the config or the middleware | ||
$paths = $this->getPathsByHost($request->getUri()->getHost()); | ||
|
||
foreach ($paths as $path) { | ||
if ($path !== '/') { | ||
$path = trim($path, '/'); | ||
} | ||
|
||
if ($request->getUri()->getPath() === $path || $request->getUri()->getPath() === $path) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* Paths by given host or string values in config by default | ||
* | ||
* @param string $host | ||
* @return array | ||
*/ | ||
protected function getPathsByHost(string $host): array | ||
{ | ||
// If there are paths by the given host | ||
if (isset($this->paths[$host])) { | ||
return $this->paths[$host]; | ||
} | ||
// Defaults | ||
return array_filter($this->paths, function ($path) { | ||
return is_string($path); | ||
}); | ||
} | ||
} |
Oops, something went wrong.