This is a PHP 7 Composer compatible library for providing a PSR-7 compatible middleware layer for handling "CORS" (Cross Origin Request Security/Cross-Origin Http Request/HTTP access control) headers and security.
- PHP-7 type declarations.
 - Works as a piece of PSR-7 middleware making it compatible with many frameworks (such as Slim 3 and Symfony)
 - Massively flexibility over configuration settings (most can be strings, arrays or callbacks).
 - Follows the CORs flowchart and actively rejects invalid requests.
 - Only sends the appropriate headers when necessary.
 - On CORs "OPTIONS" request, ensure a blank page 204 "No Content" page is returned instead of returning unwanted content bodies.
 - Supports PSR-3 based loggers for debugging purposes.
 - Ignores non-CORs "OPTIONS" requests (for example, on REST services). A CORs request is indicated by the presence of the Origin: header on the inbound request.
 - Fully unit tested.
 - Licensed under the MIT License allowing you to practically do whatever you want.
 - Uses namespaces and is 100% object orientated.
 - Blocks invalid settings.
 - Minimal third party requirements (just the definition files "psr/http-message" and "psr/log" as interface definitions, and PHPUnit, PHPCodeSniffer, and Monolog for development/testing).
 
Install the latest version with Composer via:
$ composer require bairwell/middleware-corsor by modifying your composer.json file:
{
  "require": {
    "bairwell/middleware-cors": "@stable"
  }
}
or from the Github repository (which is needed to be able to fork and contribute):
$ git clone git://github.com:bairwell/middleware-cors.git
You can utilise this CORs library as simply as:
$slim = new \Slim\App(); // use Slim3 as it supports PSR7 middleware
// add CORs
$slim->add(new MiddlewareCors());
// add routes
$slim->run(); // get Slim runningbut that won't really add much (as it allows all hosts origin and methods by default).
You can make it slightly more complex by:
$slim = new \Slim\App(); // use Slim3 as it supports PSR7 middleware
$config = [
    'origin' => '*.example.com' // allow all hosts ending example.com
];
// add CORs
$slim->add(new MiddlewareCors($config));
// add routes
$slim->run(); // get Slim runningor
$slim = new \Slim\App(); // use Slim3 as it supports PSR7 middleware
$config = [
    'origin' => ['*.example.com', '*.example.com.test', 'example.com', 'dev.*'],
    'allowCredentials' => true
];
$slim->add(new MiddlewareCors($config)); // add CORs
// add routes
$slim->run(); // get Slim runningwhich will allow all Origins ending .example.com or *.example.com.test, the exact example.com origin or any host starting with dev. It'll also allow credentials to be allowed.
For a more complicated integration which relies on the Slim router to feed back which methods are actually
allowed per route, see tests/MiddlewareCors/FunctionalTests/SlimTest.php
// read the allowed methods for a route
$corsAllowedMethods = function (ServerRequestInterface $request) use ($container) : array {
    // if this closure is called, make sure it has the route available in the container.
    /* @var RouterInterface $router */
    $router = $container->get('router');
    $routeInfo = $router->dispatch($request);
    $methods = [];
    // was the method called allowed?
    if ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) {
        $methods = $routeInfo[1];
    } else {
        // if it was, see if we can get the routes and then the methods from it.
        // @var \Slim\Route $route
        $route = $request->getAttribute('route');
        
        // has the request get a route defined? is so use that
        if (null !== $route) {
            $methods = $route->getMethods();
        }
    }
    // if we have methods, let's list them removing the OPTIONs one.
    if (0 === count($methods)) {
        // find the OPTIONs method
        $key = array_search('OPTIONS', $methods,true);
        // and remove it if set.
        if (false !== $key) {
            unset($methods[$key]);
            $methods = array_values($methods);
        }
    }
    return $methods;
};
$cors = new MiddlewareCors([
    'origin' => ['*.example.com','example.com','*.example.com.test','192.168.*','10.*'],
    'exposeHeaders' => '',
    'maxAge' => 120,
    'allowCredentials' => true,
    'allowMethods' => $corsAllowedMethods,
    'allowHeaders' => ['Accept', 'Accept-Language', 'Authorization', 'Content-Type','DNT','Keep-Alive','User-Agent','X-Requested-With','If-Modified-Since','Cache-Control','Origin'],
]);
$slim->add($cors);The following PHP FIG standards should be followed:
- PSR 1 - Basic Coding Standard
 - PSR 2 - Coding Style Guide
 - PSR 3 - Logger Interface
 - PSR 4 - Autoloading Standard
 - PSR 5 - PHPDoc Standard - (still in draft)
 - PSR 7 - HTTP Message Interface
 - PSR 12 - Extended Coding Style Guide - (still in draft)
 
PHP Code Sniffer highlights potential coding standards issues.
vendor/bin/phpcs
PHP CS will use the configuration in phpcs.xml.dist by default.
To see which sniffs are running add "-s"
PHPUnit is installed for unit testing (tests are in tests)
To run unit tests:
vendor/bin/phpunit
For a list of the tests that have ran:
vendor/bin/phpunit --tap
To restrict the tests run:
vendor/bin/phpunit --filter 'MiddlewareCors\\Exceptions\\BadOrigin'
or just
vendor/bin/phpunit --filter 'ExceptionTest'
for all tests which have "Exception" in them and:
vendor/bin/phpunit --filter '(ExceptionTest::testEverything|ExceptionTest::testStub)'
to test the two testEverything and testStub methods in the ExceptionTest class (for example).
Licenced under the MIT license. See LICENSE.md for full information.
Bairwell/MiddlewareCors is Copyright (c) Bairwell Ltd/Richard Bairwell 2016.
You can help support development of this library via a variety of methods:
- "Sponsorship" via a monthly donation via Patreon
 - Reporting issues
 - Making updates via Github
 - Spreading the word.
 - Just letting me know what you think of it via Twitter or via Bairwell Ltd
 
