Rack CORS Middleware
Rack::Cors
provides support for Cross-Origin Resource Sharing (CORS) for Rack compatible web applications.
The CORS spec allows web applications to make cross domain AJAX calls without using workarounds such as JSONP. See Cross-domain Ajax with Cross-Origin Resource Sharing
Installation
Install the gem:
gem install rack-cors
Or in your Gemfile:
gem 'rack-cors', :require => 'rack/cors'
Configuration
Rack
In config.ru
, configure Rack::Cors
by passing a block to the use
command:
use Rack::Cors do
allow do
origins 'localhost:3000', '127.0.0.1:3000',
/http:\/\/192\.168\.0\.\d{1,3}(:\d+)?/
# regular expressions can be used here
resource '/file/list_all/', :headers => 'x-domain-token'
resource '/file/at/*',
:methods => [:get, :post, :put, :delete, :options],
:headers => 'x-domain-token',
:expose => ['Some-Custom-Response-Header'],
:max_age => 600
# headers to expose
end
allow do
origins '*'
resource '/public/*', :headers => :any, :methods => :get
end
end
Rails
Put something like the code below in config/application.rb
of your Rails application. For example, this will allow GET, POST or OPTIONS requests from any origin on any resource.
module YourApp
class Application < Rails::Application
# ...
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
end
end
Refer to rails 3 example and rails 4 example for more details.
See The Rails Guide to Rack for more details on rack middlewares or watch the railscast
Configuration Reference
Middleware Options
- debug (boolean): Enables debug logging and
X-Rack-CORS
HTTP headers for debugging. - logger (Object or Proc): Specify the logger to log to. If a proc is provided, it will be called when a logger is needed (this is helpful in cases where the logger is initialized after
Rack::Cors
is used, likeRails.logger
.
Origin
Origins can be specified as a string, a regular expression, or as '*' to allow all origins.
Resource
A Resource path can be specified as exact string match (/path/to/file.txt
) or with a '' wildcard (`/all/files/in/`). A resource that take the following options:
- methods (string or array): The HTTP methods allowed for the resource.
- headers (string or array or
:any
): The HTTP headers that will be allowed in the CORS resource request. Use:any
to allow for any headers in the actual request. - expose (string or an array): The HTTP headers in the resource response can can be exposed to the client.
- credentials (boolean): Sets the
Access-Control-Allow-Credentials
response header. - max_age (number): Sets the
Access-Control-Max-Age
response header.
Common Gotchas
Incorrect positioning of Rack::Cors
in the middleware stack can produce unexpected results. The Rails example above will put it above all middleware which should cover most issues.
Here are some common cases:
Serving static files. Insert this middleware before
ActionDispatch::Static
so that static files are served with the proper CORS headers (see note below for a caveat). NOTE: that this might not work in production environments as static files are usually served from the web server (Nginx, Apache) and not the Rails container.Caching in the middleware. Insert this middleware before
Rack::Cache
so that the proper CORS headers are written and not cached ones.Authentication via Warden Warden will return immediately if a resource that requires authentication is accessed without authentication. If
Warden::Manager
is in the stack beforeRack::Cors
, it will return without the correct CORS headers being applied, resulting in a failed CORS request. Be sure to insert this middleware before 'Warden::Manager`.
To determine where to put the CORS middleware in the Rack stack, run the following command:
bundle exec rake middleware
In many cases, the Rack stack will be different running in production environments. For example, the ActionDispatch::Static
middleware will not be part of the stack if config.serve_static_assets = false
. You can run the following command to see what your middleware stack looks like in production:
bundle exec RAILS_ENV=production rake middleware