Skip to content
This repository has been archived by the owner on May 23, 2022. It is now read-only.

Commit

Permalink
Merge pull request #25 from ozee31/chrisShick-master
Browse files Browse the repository at this point in the history
  • Loading branch information
ozee31 authored May 14, 2020
2 parents da42a1a + 0d50de2 commit fc45012
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 66 deletions.
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

[![Build Status](https://travis-ci.org/ozee31/cakephp-cors.svg?branch=master)](https://travis-ci.org/ozee31/cakephp-cors)

A CakePHP (3.3+) plugin for activate cors domain in your application with [Middleware](http://book.cakephp.org/3.0/en/controllers/middleware.html).
A CakePHP (4+) plugin for activate cors domain in your application with [Middleware](http://book.cakephp.org/3.0/en/controllers/middleware.html).

[Learn more about CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS)

**For cake 3.3+ use branch [cake-3](https://github.com/ozee31/cakephp-cors/tree/cake-3)**

## Requirements

- PHP version 5.6 or higher
- CakePhp 3.3 or higher
- PHP version 7.2 or higher
- CakePhp 4.0 or higher

## Installation

Expand All @@ -26,8 +28,12 @@ composer require ozee31/cakephp-cors
Loading the Plugin

```PHP
// In config/bootstrap.php
Plugin::load('Cors', ['bootstrap' => true, 'routes' => false]);
// In src/Application.php
public function bootstrap(): void
{
// code ...
$this->addPlugin('Cors');
}
```

By default the plugin authorize cors for all origins, all methods and all headers and caches all for one day.
Expand Down
9 changes: 6 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
"description": "A CakePHP (3.3.x) plugin for activate cors domain in your application",
"type": "cakephp-plugin",
"require": {
"php": ">=5.6",
"cakephp/cakephp": ">=3.3.2 <4.0.0"
"php": ">=7.2.0",
"cakephp/cakephp": "^4.0",
"psr/http-server-handler": "^1.0",
"psr/http-server-middleware": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "5.*"
"phpunit/phpunit": "~8.5.0",
"cakephp/cakephp-codesniffer": "^4.0"
},
"autoload": {
"psr-4": {
Expand Down
12 changes: 3 additions & 9 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
colors="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="./tests/bootstrap.php"
>
<php>
Expand Down Expand Up @@ -31,13 +30,8 @@

<!-- Prevent coverage reports from looking in tests and vendors -->
<filter>
<blacklist>
<directory suffix=".php">./vendor/</directory>
<directory suffix=".ctp">./vendor/</directory>

<directory suffix=".php">./tests/</directory>
<directory suffix=".ctp">./tests/</directory>
</blacklist>
<whitelist>
<directory suffix=".php">src/</directory>
</whitelist>
</filter>

</phpunit>
15 changes: 5 additions & 10 deletions src/Error/AppExceptionRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@
namespace Cors\Error;

use Cake\Core\Configure;
use Cake\Event\Event;
use Cake\Network\Request;
use Cake\Network\Response;
use Cake\Routing\Router;
use Exception;
use Cake\Controller\Controller;
use Cors\Routing\Middleware\CorsMiddleware;

function get_dynamic_parent() {
Expand All @@ -16,19 +12,18 @@ class_alias(get_dynamic_parent(), 'Cors\Error\BaseExceptionRenderer');

class AppExceptionRenderer extends BaseExceptionRenderer
{

/**
* Returns the current controller.
*
* @return \Cake\Controller\Controller
*/
protected function _getController()
protected function _getController(): Controller
{
$controller = parent::_getController();
$cors = new CorsMiddleware();
$controller->response = $cors(
$controller->request, $controller->response,
function($request, $response){ return $response; }
$controller->response = $cors->addHeaders(
$controller->getRequest(),
$controller->getResponse()
);
return $controller;
}
Expand Down
8 changes: 8 additions & 0 deletions src/Plugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
namespace Cors;

use Cake\Core\BasePlugin;

class Plugin extends BasePlugin
{
}
68 changes: 44 additions & 24 deletions src/Routing/Middleware/CorsMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,52 @@
use Cake\Core\Configure;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class CorsMiddleware
class CorsMiddleware implements MiddlewareInterface
{

/**
* PHPCS docblock fix needed!
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next) {
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$response = $handler->handle($request);

$response = $this->addHeaders($request, $response);

return $response;
}

public function addHeaders(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
if ($request->getHeader('Origin')) {
$response = $response
->withHeader('Access-Control-Allow-Origin', $this->_allowOrigin($request))
->withHeader('Access-Control-Allow-Credentials', $this->_allowCredentials())
->withHeader('Access-Control-Max-Age', $this->_maxAge())
->withHeader('Access-Control-Expose-Headers', $this->_exposeHeaders())
;
->withHeader('Access-Control-Max-Age', $this->_maxAge());

if (strtoupper($request->getMethod()) === 'OPTIONS') {
$response = $response
->withHeader('Access-Control-Expose-Headers', $this->_exposeHeaders())
->withHeader('Access-Control-Allow-Headers', $this->_allowHeaders($request))
->withHeader('Access-Control-Allow-Methods', $this->_allowMethods())
;
return $response;
->withHeader('Access-Control-Allow-Methods', $this->_allowMethods());
}

}

return $next($request, $response);
return $response;
}


/**
* PHPCS docblock fix needed!
* @param \Psr\Http\Message\ServerRequestInterface $request
* @return array|string
*/
private function _allowOrigin($request) {
private function _allowOrigin(ServerRequestInterface $request)
{
$allowOrigin = Configure::read('Cors.AllowOrigin');
$origin = $request->getHeader('Origin');

Expand All @@ -59,36 +73,41 @@ private function _allowOrigin($request) {
}

/**
* PHPCS docblock fix needed!
* @return String
*/
private function _allowCredentials() {
private function _allowCredentials(): String
{
return (Configure::read('Cors.AllowCredentials')) ? 'true' : 'false';
}

/**
* PHPCS docblock fix needed!
* @return String
*/
private function _allowMethods() {
private function _allowMethods(): String
{
return implode(', ', (array) Configure::read('Cors.AllowMethods'));
}

/**
* PHPCS docblock fix needed!
* @param \Psr\Http\Message\ServerRequestInterface $request
* @return String
*/
private function _allowHeaders($request) {
private function _allowHeaders(ServerRequestInterface $request): String
{
$allowHeaders = Configure::read('Cors.AllowHeaders');

if ($allowHeaders === true) {
return $request->getHeader('Access-Control-Request-Headers');
return $request->getHeaderLine('Access-Control-Request-Headers');
}

return implode(', ', (array) $allowHeaders);
}

/**
* PHPCS docblock fix needed!
* @return String
*/
private function _exposeHeaders() {
private function _exposeHeaders(): String
{
$exposeHeaders = Configure::read('Cors.ExposeHeaders');

if (is_string($exposeHeaders) || is_array($exposeHeaders)) {
Expand All @@ -99,9 +118,10 @@ private function _exposeHeaders() {
}

/**
* PHPCS docblock fix needed!
* @return String
*/
private function _maxAge() {
private function _maxAge(): String
{
$maxAge = (string) Configure::read('Cors.MaxAge');

return ($maxAge) ?: '0';
Expand Down
5 changes: 1 addition & 4 deletions tests/TestCase/Controller/ErrorControllerTest.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<?php
namespace Cors\TestCase\Controller;
namespace Cors\Tests\TestCase\Controller;

use PHPUnit\Framework\TestCase;
use Cake\Network\Request;
use Cake\Network\Response;
use Cake\Event\Event;

class ErrorControllerTest extends TestCase
{
Expand Down
37 changes: 27 additions & 10 deletions tests/TestCase/Middleware/CorsMiddlewareTest.php
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
<?php
namespace Cors\TestCase\Middleware;
namespace Cors\Tests\TestCase\Middleware;

use Cake\Http\Response;
use PHPUnit\Framework\TestCase;
use Cake\Http\ServerRequestFactory;
use Cake\Http\Response;
use Cors\Routing\Middleware\CorsMiddleware;
use Cors\Middleware\CorsMiddleware;
use Cake\Core\Configure;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

class CorsMiddlewareTest extends TestCase {

private $server = [];

const BASE_ORIGIN = 'http://test.com';

public function setUp()
public function setUp(): Void
{
parent::setUp();
$this->server = [
Expand All @@ -33,12 +36,9 @@ private function _setServer(Array $server)
private function _sendRequest()
{
$request = ServerRequestFactory::fromGlobals($this->server);
$response = new Response();
$handler = new RequestHandlerStub();
$middleware = new CorsMiddleware();
$next = function ($request, $response) {
return $response;
};
$response = $middleware($request, $response, $next);
$response = $middleware->process($request, $handler);
return $response;
}

Expand Down Expand Up @@ -85,7 +85,7 @@ public function testDefaultValuesIfIsAOptionsRequest()
$response = $this->_sendRequest();
$headers = $response->getHeaders();

$this->assertEquals([], $headers['Access-Control-Allow-Headers']);
$this->assertEquals('', current($headers['Access-Control-Allow-Headers']));
$this->assertEquals('GET, POST, PUT, PATCH, DELETE', current($headers['Access-Control-Allow-Methods']));
$this->assertEquals('', current($headers['Access-Control-Expose-Headers']));
}
Expand Down Expand Up @@ -224,3 +224,20 @@ public function testMaxAgeFalse()
$this->assertEquals(0, $responseMaxAge);
}
}

class RequestHandlerStub implements RequestHandlerInterface
{
public $callable;

public function __construct(?callable $callable = null)
{
$this->callable = $callable ?: function ($request) {
return new Response();
};
}

public function handle(ServerRequestInterface $request): ResponseInterface
{
return ($this->callable)($request);
}
}
2 changes: 1 addition & 1 deletion tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@
chdir($root);
require $root . '/vendor/cakephp/cakephp/tests/bootstrap.php';

Plugin::load('Cors', ['bootstrap' => true, 'path' => dirname(dirname(__FILE__)) . DS]);
Plugin::getCollection()->add(new \Cors\Plugin(['bootstrap' => true, 'path' => dirname(dirname(__FILE__)) . DS]));

0 comments on commit fc45012

Please sign in to comment.