Silex CORS provider for OPTIONS (preflight) requests

One part of using Silex as your framework when building an API that can be a little fiddly is CORS issues when making requets from javascript apps. I’ve started using a very simple solution for this that seems to be easier and faster than most providers.

The issue here is that the requesting application is making an OPTIONS request to see whether it can make the actual request and by default Silex won’t return the response the JS app is hoping for.

Luckily, fixing this is very simple. What we need is an OPTIONS route for each of our POST, GET etc routes. Many providers solve this by looping through each route defined in your app and creating a corresponding OPTIONS route. Even for small apps however, this is adding unnecessary processing and for large apps with lots of routes it is even slower.

To get around this, I’ve started adding two bits of code to my apps. The first should go in your bootstrap/app file.

2    $app->after(function (Request $request, Response $response) {
3        $response->headers->set('Access-Control-Allow-Origin', '*');
4        $response->headers->set('Access-Control-Allow-Headers', 'Authorization');
5    });

What this does is add two headers to all responses after the controller has finished executing but before the response is returned. Here we’ve added the Access-Control-Allow-Origin header the javascript app is looking for. I’m also telling the app that sending an Authorization header is fine too. You can remove that line if you don’t need it.

We still have an issue though, all of the GET and POST requests defined in the routes will have the correct headers, but Silex still doesn’t know what to do with the OPTIONS requests. Fixing that is as easy as adding the following snippet to your routes files.

2    $app->options("{anything}", function () {
3        return new \Symfony\Component\HttpFoundation\JsonResponse(null, 204);
4    })->assert("anything", ".*");

All we’re doing here is matching against any OPTIONS requests and returning a 204 response with no content. The code we added earlier will still apply to this response so our headers are correct. If you wanted, you could check inside the function to see whether the URL matches a URL in your non OPTIONS routes.

comments powered by Disqus