jdesrosiers / silex-cors-provider

A silex service provider that adds CORS services to silex
MIT License
78 stars 25 forks source link

Equivalent routes with different request method #27

Closed marvinGitHub closed 8 years ago

marvinGitHub commented 8 years ago

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.

jdesrosiers commented 8 years ago

Thanks for the bug report. I'll be able to look into it in about a week.

marvinGitHub commented 8 years ago

Hello Jason Desrosiers, are you able to reproduce this kind of error? I havent found any solution yet to fix this problem, because symfony uses its own expression to match routes and not PCREs. It will be fairly simple to match all routes and detect the request method if they would use PCREs.

jdesrosiers commented 8 years ago

I looked into this, and I think the only issue is the order you declare the routes. If you declare /seaman/search/ before /seaman/{id}/, it will work as expected. If it were a simple request, the order wouldn't matter because the different methods differentiate the two requests. However the CORS preflight request is always an OPTIONS request. The simple routes combined with the generated preflight routes are listed below in the order they are defined.

When a POST /seaman/search/ request is issued, the browser first makes an OPTIONS /seaman/search/ CORS preflight request. The first OPTIONS request matches and therefore responds with a Access-Control-Allowed-Methods header of GET instead of POST causing the browser to refuse the request. If the routes are switched, the OPTIONS /seaman/search/ route is tried first and everything works as expected.

It's unfortunate that you need to know how this stuff works to avoid this problem, but I don't think there is a good way around it. I think the best I can do is to put a note in the README to steer people in the right direction.