Skip to content
This repository has been archived by the owner on Apr 2, 2024. It is now read-only.

Latest commit

 

History

History
139 lines (97 loc) · 6.56 KB

README.md

File metadata and controls

139 lines (97 loc) · 6.56 KB

Rack CORS Middleware Build Status

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'

Configuration

Rails Configuration

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
    # ...
    
    # Rails 5

    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins '*'
        resource '*', headers: :any, methods: [:get, :post, :options]
      end
    end

    # Rails 3/4

    config.middleware.insert_before 0, "Rack::Cors" do
      allow do
        origins '*'
        resource '*', headers: :any, methods: [:get, :post, :options]
      end
    end
  end
end

We use insert_before to make sure Rack::Cors runs at the beginning of the stack to make sure it isn't interfered with by other middleware (see Rack::Cache note in Common Gotchas section). Check out the rails 4 example and rails 3 example.

See The Rails Guide to Rack for more details on rack middlewares or watch the railscast.

Rack Configuration

NOTE: If you're running Rails, updating in config/application.rb should be enough. There is no need to update config.ru as well.

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',
            /\Ahttp:\/\/192\.168\.0\.\d{1,3}(:\d+)?\z/
            # regular expressions can be used here

    resource '/file/list_all/', :headers => 'x-domain-token'
    resource '/file/at/*',
        methods: [:get, :post, :delete, :put, :patch, :options, :head],
        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

    # Only allow a request for a specific host
    resource '/api/v1/*',
        headers: :any,
        methods: :get,
        if: proc { |env| env['HTTP_HOST'] == 'api.example.com' }
  end
end

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 initially configured, like Rails.logger.

Origin

Origins can be specified as a string, a regular expression, or as '*' to allow all origins.

*SECURITY NOTE: Be careful when using regular expressions to not accidentally be too inclusive. For example, the expression /https:\/\/example\.com/ will match the domain example.com.randomdomainname.co.uk. It is recommended that any regular expression be enclosed with start & end string anchors (\A\z).

Additionally, origins can be specified dynamically via a block of the following form:

  origins { |source, env| true || false }

A Resource path can be specified as exact string match (/path/to/file.txt) or with a '*' wildcard (/all/files/in/*). To include all of a directory's files and the files in its subdirectories, use this form: /assets/**/*. A resource can take the following options:

  • methods (string or array or :any): 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 array): The HTTP headers in the resource response can be exposed to the client.
  • credentials (boolean, default: false): Sets the Access-Control-Allow-Credentials response header. Note: If a wildcard (*) origin is specified, this option cannot be set to true. Read this security article for more information.
  • max_age (number): Sets the Access-Control-Max-Age response header.
  • if (Proc): If the result of the proc is true, will process the request as a valid CORS request.
  • vary (string or array): A list of HTTP headers to add to the 'Vary' 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::Manageris in the stack before Rack::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:

RAILS_ENV=production bundle exec rake middleware