I’m currently writing a
to directly call a
REST-style API (implemented with
CORS (Cross-Origin Resource Sharing) is new technique makes it possible for AJAX requests to directly talk to HTTP-services outside it’s own domain. Read this awesome primer to read more on CORS.
While there are lots of examples that show how to allow CORS requests in Rails (just google), they almost never have tests with them. While it’s simple to test the HTTP headers, you may have to look around a little (or a lot) on how to test a HTTP “OPTIONS” request. When you make CORS requests, the browser may make a pre-flight “OPTIONS” request to verify that the server allows CORS.
To make Rails set the right HTTP headers to allow CORS requests, you can do something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
A few things to note here:
You can set the
Access-Control-Allow-Originheader to your domain to further restrict it.
While Rails is one place to do this in, you can certainly do this in your webserver (nginx etc.). Again, just google. I prefer things to be more testable – maybe when I see a performance problem, I’d revise this decision (although, performance bottlenecks would probably not be in setting HTTP headers).
Another thing to consider when you allow CORS, is authentication – you should do some HTTP based auth (token auth for example) so only your apps can talk to this service. The thing with JS is, however uglified it is, any developer worth his salt can figure out how to call your backend service after reading your JS by loading your site up in a browser.
In any case, how do you test this? It’s fairly trivial to test that the right HTTP headers were set with something like this:
To make a HTTP
options request in RSpec, I had to dig through some
code. And googling didn’t help here, at least the way I google. Here’s
RSpec delegates the request methods (like
put etc. in the controller specs) to Rails’
ActionController Tests. All these methods invoke
ActionController::TestCase#process with specific args, one of which
is the method name.
Now, Rails master already has support for making
options requests in tests (thanks to this commit), but that’s
not available in the latest Rails release (3.2.8). I think this would
make it’s way into Rails 4.
Looking into this commit, we get the idea
though: basically we also call the
process method with a
argument for the request-method. Putting it all together, my tests
looked something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Update for Rails 4
@ekampp on twitter
brought it to my attention that this test does not work
anymore. It appears that the
options method was
added and then
removed from Rails
master (since a method named
options conflicts with a lot of stuff,
as you can imagine).
So, in Rails 4 (and current master) you can call
head is implemented. So you are basically doing the same
thing for an