How to Fix Access-Control-Allow-Origin Error in Ruby on Rails

If you're trying to make an API to allow your site's content to be accessible via JavaScript from another site, you've probably run into the error "XMLHttpRequest cannot load XXX. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'YYY' is therefore not allowed access." where XXX is the resource you were trying to fetch and YYY is the domain of the page that loaded the JavaScript that was trying to fetch XXX.

In this blog post, I'll show you how to fix that problem if your API is based on Ruby on Rails.

If you're trying to setup an API, then you're probably going to be accessing it with JavaScript from the browser. In that case, I recommend reading Understanding ECMAScript 6: The Definitive Guide for JavaScript Developers to get caught up on all the new features added to JavaScript in 2015.

Add rack-cors to Your Gemfile

First, you'll need to add rack-cors to your Gemfile and run bundle install. Rack-cors is Rack middleware for handling Cross-Origin Resource Sharing (CORS), which makes cross-origin AJAX possible.

# Gemfile
gem 'rack-cors', :require => 'rack/cors'

Configure Origins to Allow and Resources to Share

Next, open up your config/application.rb file and add the lines below:

# config/application.rb

...

  class Application < Rails::Application
    # Access-Control-Allow-Origin
    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins 'localhost:3000', /https*:\/\/.*?bloopist\.com/
        resource '*', :headers => :any, :methods => :any
      end
    end
  end

The array that is passed to origins tells rack-cors from which domains to allow Cross-Origin Resource Sharing. This array can contain both strings and regular expressions. Notice that I'm allowing localhost (for development purposes) and all of the Bloopist domain. The Bloopist regular expression allows resource sharing to pages that are loaded through http or https on any subdomain of bloopist.com.

The arguments passed to resource tell rack-cors what which paths to allow the domains passed to origins to access. To allow access to all paths in your application, pass '*'. If you're making an API, then you probably want this to be something like '/api'

For more information on how to set up the origins and resources you're sharing with rack-cors, see the rack-cors documentation.

Was the information in this blog post helpful? Is there something that you think needs to be added? Let me know in the comments!

Photo by Beyond Coal & Gas Image Library