I’ve not found any blog post or article about how to easily test CORS support implemented in a Rack middleware (e.g. using the rack-cors gem) with RSpec in Rails. So, after figured out I decided to write some small tips I learned from it.
I assume you have a fairly updated Rails app, I tested it with Rails 4.2.x, with RSpec
tests support, and you want to add support for CORS
headers.
Install rack-cors gem
it’s better to follow the gem instructions (you’ll find the most updated instructions there) than a blog post, but anyway here’s how I did it:
Add this to your Gemfile
:
1
|
|
Add this to your config/application.rb
:
1 2 3 4 5 6 |
|
These are the common options, tune it to your needs. Here we’re allowing requests from any domain for the get
, post
, patch
and options
methods. options
is a special method used for preflight requests.
That’s it. CORS
is now active in this Rails app. Every time we send a request with the CORS
headers, we’ll receive the CORS
response headers.
How to test it with cURL
With cURL, it’s easy to test CORS
. Let’s see the most common scenarios:
Sending the Origin
header:
-H
: Header to include in the request.-I
: Fetch theHTTP
header only.
1
|
|
We should receive: Access-Control-Allow-Origin: *
.
Sending the preflight options method:
Send a options request with Origin: *
, Access-Control-Request-Method: get
and Access-Control-Request-Headers: test
.
* -X
: Specifies a custom request method
1
|
|
We should receive Access-Control-Allow-Origin: *
, Access-Control-Allow-Methods: get, post, patch, options
, and Access-Control-Allow-Headers: test
.
How to test it with RSpec
Support CORS is a bit tricky to test with RSpec
, because we don’t have a real server (like Webrick, Unicorn or Puma) between the code and the client. This usually is not a problem but it does affect in this particular case, and the rfc3875 explains why. The server translate the custom HTTP
request headers in this way:
- Convert to upper case.
- Replace
-
with_
- Prepend
HTTP_
.
Because we don’t have the server to do it for us, we must do it manually. For example, the Origin
becomes HTTP_ORIGIN
and Http-Access-Control-Request-Method
becomes HTTP_ACCESS_CONTROL_REQUEST_METHOD
.
Let’s see some example tests:
Sending the Origin header:
1 2 3 4 5 6 7 |
|
Sending the preflight options method:
1 2 3 4 5 6 7 8 9 10 |
|
Note: You must use integration tests to be able the test through rack
. A controller test doesn’t trigger rack
, it’s like an unit test for the controller.
Don’t forget to uppercase, replace -
and prepend HTTP_
to all your custom HTTP headers when testing!