Git Product home page Git Product logo

silex-cors-provider's Introduction

silex-cors-provider

Build Status Scrutinizer Code Quality Code Coverage

The CorsServiceProvider provides CORS support as middleware for your silex application. CORS allows you to make AJAX requests across domains. CORS uses OPTIONS requests to make preflight requests. Because silex doesn't have functionality for serving OPTIONS request by default, this service goes through all of your routes and generates the necessary OPTIONS routes.

Installation

Install the silex-cors-provider using composer. This project uses sematic versioning.

composer require jdesrosiers/silex-cors-provider "~1.0"

Parameters

  • cors.allowOrigin: (string) Space separated set of allowed domains (wildcards allowed e.g. http://*.example.com). Defaults to all.
  • cors.allowMethods: (string) Comma separated set of allowed HTTP methods. Defaults to all.
  • cors.allowHeaders: (string) Comma separated set of allowed HTTP request headers. Defaults to all.
  • cors.maxAge: (int) The number of seconds a CORS pre-flight response can be cached. Defaults to 0.
  • cors.allowCredentials: (boolean) Are cookies allowed? Defaults to false.
  • cors.exposeHeaders: (string) Comma separated set of headers that are safe to expose. Defaults to none. This should not include the six simple response headers which are always exposed: Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma.

Services

  • cors: A function that can be added as after middleware to the Application. (Deprecated. Use cors-enabled instead)
  • cors-enabled: Pass this function an Application, a ControllerCollection, or a Controller and it will enable CORS support for every route the object defines. Optionally, you can pass an array of options as a second parameter. The options you can pass are the same as the cors.* parameters without the cors. part. This is useful of you need different configuration for different routes.
  • options: Similar to cors-enabled but only creates OPTIONS routes with no CORS support.
  • allow: A function that can be added as after middleware to an Application, a ControllerCollection, or a Controller that will add an Allow header to every route the object defines.

Registering

$app->register(new JDesrosiers\Silex\Provider\CorsServiceProvider(), [
    "cors.allowOrigin" => "http://petstore.swagger.wordnik.com",
]);

Usage

Add CORS functionality to the entire application.

$app->get("/foo/{id}", function ($id) { /* ... */ });
$app->post("/foo/", function () { /* ... */ });

$app["cors-enabled"]($app);

Add CORS functionality to a controller collection.

$foo = $app["controllers_factory"];
$foo->get("/{id}", function () { /* ... */ });
$foo->post("/", function () { /* ... */ });
$app->mount("/foo", $app["cors-enabled"]($foo));

$app->get("/bar/{id}", function ($id) { /* ... */ }); // Not CORS enabled

Add CORS functionality to a controller.

$controller = $app->get("/foo/{id}", function ($id) { /* ... */ });
$app["cors-enabled"]($controller);
$app->post("/foo/", function () { /* ... */ }); // Not CORS enabled

silex-cors-provider's People

Contributors

adlacruzes avatar adrianbardan avatar alcalyn avatar cyberwolf avatar jdesrosiers avatar jeromemacias avatar jrschumacher avatar leggetter avatar macmee avatar mcuadros avatar slipo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

silex-cors-provider's Issues

Access-Control-Expose-Headers should be comma, not space separated

Hello,

According to Mozilla MDN here,
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

Access-Control-Expose-Headers should be comma, not space separated. It also defaults to none, not to all.

We've seen this when testing with Angular 2 Client on Google Chrome. The Angular 2 client doesn't see the headers we've sent (Location for example) if the list of allowed headers is not comma separated.

You probably need to update your documentation and tests.

Extract "domain" class that would be framework agnostic

As mentioned here, it would be nice to have a class that would be CORS–oriented, but not framework oriented.

It would prepare response headers, tell if the request is preflight, etc.

It would still be based upon Symfony's Request/Response, but would be Symfony/Silex agnostic (i.e.: configured without knowing of Silex:Application class, would not be a Silex:filter, etc).

Cannot get to work inside a ControllerProviderInterface implemented Class

Hi, I might be doing something wrong here but I'm trying to get it working like this

public function connect(Application $app){
    $factory = $app['controllers_factory'];
    $factory->post('/', 'Classes\Routes\FaqsController::create');
    $factory->after($app["cors"]);
}

I can get it working on normal routes, just not one inside the controllers_factory I've created.

I'm getting this error
Symfony\Component\HttpKernel\Exception\NotFoundHttpException: No route found for "OPTIONS /faqs" (from "http://localhost:3000/") (uncaught exception) at /media/sf_localhost/dev.api.nitritex.com/vendor/symfony/http-kernel/EventListener/RouterListener.php line 159 {"exception":"[object](Symfony\Component\HttpKernel\Exception\NotFoundHttpException%28code: 0%29: No route found for "OPTIONS /faqs" %28from "http://localhost:3000/"%29 at /media/sf_localhost/dev.api.nitritex.com/vendor/symfony/http-kernel/EventListener/RouterListener.php:159, Symfony\Component\Routing\Exception\ResourceNotFoundException%28code: 0%29: No routes found for "/faqs". at /media/sf_localhost/dev.api.nitritex.com/vendor/symfony/routing/Matcher/UrlMatcher.php:102)"} []

Apologies if this is the wrong place to post this.

Accept all subdomains and different protocols instead of a precise host

Hi,

in my app I cannot specify all exact hosts that should be accepted. I need to whitelist all subdomains for some domain. Whitelisting any protocol would be nice as well (although I need two, http and https, so it's not much duplication).

I don't want to do: http://example.com https://example.com http://mobile.example.com https://mobile.example.com… I don't even know which subdomains are ok, I need them all.

I want to do something like *.example.com and this should match all the above.

I've implemented it myself, but it required copy–pasting and modifying Cors class, as it's not extensible in any way (no composition and its methods are private).

domainToRegex does not allow protocol on wildcards

    private function domainToRegex($domain)
    {
        return "/^" . preg_replace("/^\\\\\*/", "[^.]+", preg_quote($domain, "/")) . "$/";
    }

This regex only allows for wildcards without protocol (e.g. *.website.com).

The ^ regex should be remove to allow users to provide protocol for wildcard domains.

E.g. return "/^" . preg_replace("/\\\\\*/", "[^.]+", preg_quote($domain, "/")) . "$/";

Equivalent routes with different request method

Hello Jason Desrosiers,
i have observed an issue inside the CorsServiceProvider logic. The application i have created with silex has two routes which are almost identical

$application->get("/seaman/{id}/", function($id){ ... }); $application->post("/seaman/search/", function(Request $request){ ... });

In line 64 of CorsServiceProvider.php the "match" method will always match the first route. According to the definition of the first route, its expected to be a GET request, so when i started a POST request on route "/seaman/search/", the request will abort because the server responds with the control header of the first route.

OPTION method not injected when using optional parameter in route

Hello,
first of all thank you very much for this!

I'm not sure is a problem with your class or what, so apologies if it is not.
I started experiencing this problem when I moved routes from a single file to controller providers so the problem might be there.

I have a route that matches /customer and I then mount to it other sub routes. The first defined is

  path: '{id}'
  defaults: { _controller: 'customer.controller:getAction', id: 0 }
  requirements:
    id: \d+
  methods: [GET]

so that should match both /customer and /customer/3.

If I try to access the route /customer directly it is resolved, if I try to access it with a browser and a using CORS, it will detect the route but it will fail saying OPTION is not a method allowed. I have the feeling that the OPTION method has been injected in the /customer/ route instead of the /customer but I have no way to prove it :D

Do you have idea why this is happening?
I hope to have been clear enough!

===UPDATE===
I managed to recreate the same and also managed to prove that OPTIONS method is attached to the route with the trailing slash not to the one without while the silex router resolve the latter.

Where is 'cors-enabled' in 1.6.0 ?

Hi,

Following the doc with version 1.6 to register and enable the service generate me an error with a function not found for cors-enabled.
I can see that the function disappeared between version 1.5 and 1.6. What should we use now ?

Thanks!

Adding after middleware to ControllerCollection does not add preflight headers

For one of my applications, I do need CORS handling but I can not use it for all routes.

I then added the after middleware to some routes.

The OPTIONS routes are properly added but then, the after $app['cors'] is not called on these generated routes. The consequence is that although the OPTIONS route exists, I does not return Access-Control-Allow-Origin header on the preflight calls.

Are there any ways to add the OPTIONS routes to ControllerCollections instead of after all routes are added?

405 rather than a 404 on route not found

CorsServiceProvider makes the OPTIONS method available for any path. If I do a GET request to a route that doesn't exist, Silex returns a 405 Method Not Allowed rather than the expected 404 Not Found.

Access-Control-Allow-Origin returns 'null' for unauthorized origins

Reproduction

  1. Allow requests from a specific origin only
$app->register(new CorsServiceProvider(), array(
    "cors.allowOrigin" => "http://foo.com",
));
  1. Make a request from a different origin

curl -X GET -H "Origin: http://bar.com" -I http://api

Expected result

No Access-Control-Allow-Origin is sent at all

Actual result

Access-Control-Allow-Origin is set to null

Remarks

There is a test that explicitly tests for this behavior. Therefore I'm not sure if this is intentional or not.

Show a full app example.

I tried to get it to work on a simple silex app, it doesn't work.

<?php
require_once __DIR__.'/../vendor/autoload.php';

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ParameterBag;
use JDesrosiers\Silex\Provider\CorsServiceProvider;

$app = new Silex\Application();
$app->register(new CorsServiceProvider());

$app->before(function (Request $request) {
    if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
        $data = json_decode($request->getContent(), true);
        $request->request->replace(is_array($data) ? $data : array());
    }
});

$app->get('/', function () use ($app) {
    $return = array('hi');
    return $app->json($return, 200);
});

$app->post('/test', function (Request $request) use ($app) {
        return $app->json('success', 200);
 });

$app->after($app["cors"]);

$app->run();

Request matcher

When using the Silex security service provider, CORS preflight requests get halted by the firewall on secured paths.

It would be handy if this package could offer a RequestMatcher implementation to match these preflight requests and let them pass through the firewall. I could then configure the firewall as follows:

$app['security.firewalls'] = array(
    'authentication' => array(
        'pattern' => '^/auth',
    ),
    'cors-preflight' => array(
        'pattern' => $app['cors_preflight_request_matcher'],
    ),
    'secured' => array(
        'pattern' => '^.*$',
        'uitid' => true,
        'users' => $app['uitid_firewall_user_provider'],
    ),
);

I have some working code already in our project (https://github.com/cultuurnet/silex-uitid-provider/blob/master/src/Security/PreflightRequestMatcher.php), I'd be happy to extract it and contribute it through a pull request, unless you see a better way to accomplish this?

Compatibility with Symfony routing 2.7.x

Hi,

I tried upgrading to Symfony routing component 2.7 but the cors provider causes some Deprecated PHP notices:

Deprecated: The "_method" requirement is deprecated since version 2.2 and will be removed in 3.0.
Use the setMethods() method instead or the "methods" option in the route definition.

The CorsServiceProvider has a couple weaknesses

The CorsServiceProvider has a couple weaknesses.
1. It generates OPTIONS routes even if OPTIONS routes already exist. I think this feature needs to check if the route already exists before creating one.
2. It would probably be better if OPTIONS route generation did not happen automatically. The developer should have control over if and when this functionality is executed.
3. The cors service allows you to apply the middleware at whatever level you choose. The idea is that one controller might have different requirements than another controller, and a third controller might not support CORS at all. The current solution covers the case where one controller uses CORS but another doesn't. The case where one controller has different CORS settings than another is difficult to express with the current architecture.

Silex 1.2-stable compatility?

I'm interested in using this but would rather not upgrade to silex 2.0-dev.

I tried just switching to stable deps (https://github.com/EdwardIII/silex-cors-provider) but this does break the package:

PHP Fatal error:  Interface 'Pimple\ServiceProviderInterface' not found in /private/tmp/silex-cors-provider/src/CorsServiceProvider.php on line 16
PHP Stack trace:
PHP   1. {main}() /usr/local/Cellar/phpunit/4.3.4/libexec/phpunit-4.3.4.phar:0
PHP   2. PHPUnit_TextUI_Command::main() /usr/local/Cellar/phpunit/4.3.4/libexec/phpunit-4.3.4.phar:605
PHP   3. PHPUnit_TextUI_Command->run() phar:///usr/local/Cellar/phpunit/4.3.4/libexec/phpunit-4.3.4.phar/phpunit/TextUI/Command.php:138
PHP   4. PHPUnit_TextUI_TestRunner->doRun() phar:///usr/local/Cellar/phpunit/4.3.4/libexec/phpunit-4.3.4.phar/phpunit/TextUI/Command.php:186
PHP   5. PHPUnit_Framework_TestSuite->run() phar:///usr/local/Cellar/phpunit/4.3.4/libexec/phpunit-4.3.4.phar/phpunit/TextUI/TestRunner.php:423
PHP   6. PHPUnit_Framework_TestCase->run() /private/tmp/silex-cors-provider/vendor/phpunit/phpunit/src/Framework/TestSuite.php:716
PHP   7. PHPUnit_Framework_TestResult->run() /private/tmp/silex-cors-provider/vendor/phpunit/phpunit/src/Framework/TestCase.php:687
PHP   8. PHPUnit_Framework_TestCase->runBare() /private/tmp/silex-cors-provider/vendor/phpunit/phpunit/src/Framework/TestResult.php:609
PHP   9. JDesrosiers\Tests\Silex\Provider\CorsServiceProviderTest->setUp() /private/tmp/silex-cors-provider/vendor/phpunit/phpunit/src/Framework/TestCase.php:727
PHP  10. spl_autoload_call() /private/tmp/silex-cors-provider/vendor/phpunit/phpunit/src/Framework/TestCase.php:19
PHP  11. Composer\Autoload\ClassLoader->loadClass() /private/tmp/silex-cors-provider/vendor/phpunit/phpunit/src/Framework/TestCase.php:0
PHP  12. Composer\Autoload\includeFile() /private/tmp/silex-cors-provider/vendor/composer/ClassLoader.php:278
PHP  13. include() /private/tmp/silex-cors-provider/vendor/composer/ClassLoader.php:386

Any pointers on how I could make this Silex 1.2 compatible?

Unable to get silex-cors-provider using compser

I just can't get your package using composer.
Here's the error message:

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - The requested package jdesrosiers/silex-cors-provider ~0.1 could not be found.

Here is my composer.json:

{
    "require": {
        "silex/silex": "1.*",
        "doctrine/dbal": "2.2.*",
        "monolog/monolog": ">=1.0.0",
        "jdesrosiers/silex-cors-provider": "~0.1"
    }
}

What's on your side?

Add support for specifying the Access-Control-Allow-Headers CORS header

As far as I know, the CorsServiceProvider can support all features in the CORS specification except one Access-Control-Allow-Headers. It cheats by hardcoding this header *. For this service to be complete, it needs to all the user to specify a value for Access-Control-Allow-Headers.

Not working with php build in server

If I start my skeleton app like this:

php -S localhost:8000

Serving this file:

<?php
require_once __DIR__ . '/../vendor/autoload.php';

$app = new Silex\Application();
$app->register(new JDesrosiers\Silex\Provider\CorsServiceProvider(), array());
$app->after($app["cors"]);

$app->get('/', function () use($app) {
    $data = array(
        'title' => 'Hello world'
    );
    return $app->json($data);
});

$app->run(); 

When I access the server from my angularjs app running on 127.0.0.1:10000 I get the following error in my browser:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8000/. (Reason: CORS request failed).

Any hints?

Having HTTP 405 Method not allowed response when used with annotations

I'm trying to make a PUT HTTP request:

The browser then send the preflight request:

Request:

OPTIONS /index-dev.php/api/teams/4/users/32 HTTP/1.1
Host: localhost:20000
Access-Control-Request-Method: PUT
origin: http://localhost
Connection: keep-alive

Response:

HTTP/1.1 405 Method Not Allowed
Server: nginx/1.11.8
Connection: keep-alive
Allow: PUT
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Origin: http://localhost

I can see the cors headers are well set, but it keeps the 405 status code and the silex error page in body which is saying that the OPTIONS method is not allowed for this controller.

I don't want to make all my controllers match the OPTIONS method.

I can see that the cors servcie does its jobs, it adds cors headers on response, but on the same response which is actually the error response.

Cors: make isCorsRequest() and isPreflightRequest() methods public

Hi,

I need to use isCorsRequest() and isPreflightRequest() in my code, outside of the Cors class.
I could just copy–paste them, but it would be nice to just reuse existing implementation.

BTW, we could make them static, as they don't contain any object state logic.

PUT/DELETE supported

Hi,
Just a quick question. Are methods PUT and DELETE supported by the solution?
I have no problem with GET / POST but the 2 other generate a blockage at the OPTION request stage

Thank you

Silex 2.x

is there a plan to support Silex 2.0?

Duplicate Access-Control-Allow-Origin

Hi, I'm using Backbone and Silex, but when I put 'cors.allowOrigin' => 'http://**.**.com.br' and do a request with Backbone, it happens:

The 'Access-Control-Allow-Origin' header contains multiple values 'http://***.***.com.br, *', but only one is allowed.

Do you know why this happens?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.