Cecily Codes A Web Development Blog
18 March 2018

Avoiding CORS Issues with Rails API and React

I wanted to write a quick post on hooking up a create-react-app React app in development with a Rails API backend server also in development, and specifically the frustrating Cross-Origin Resource Sharing error that will often pop up in the console these situations:

Screen-Shot-2018-03-18-at-4.48.53-PM

For the purposes of this post, I'll assume that we have the create-react-app development server running on localhost:3000, letting us view our app in the browser with hot reloading whenever we change our files. I'll also assume that we have our API server running on localhost:3001.

The problem arises when we try to fetch data from our backend from our React app, since the browser considers different localhost ports to be different origins. MDN has a good explanation of what CORS is, if you'd like further information - essentially, it's a "mechanism that uses additional HTTP headers to let a [browser] gain permission to access selected resources from a server on a different origin (domain) than the site currently in use." Cross-origin requests without these headers are blocked for security reasons.

The React Proxy Fix

Fortunately for us, there's a really simple solution to let us access our backend API server from a create-react-app React application without even dealing with CORS headers: we can just add a proxy to our React server to redirect the appropriate requests to the backend.

First, we'll need to make sure the urls we're fetching do not include the absolute path (i.e. http://localhost:3001). So if we ultimately want to hit the http://localhost:3001/items endpoint, we would just use the url /items in our call to the backend.

Next, we can add a proxy setting in package.json:

// other settings...
"proxy": "http://localhost:3001/"
// other settings...

With this setup, the create-react-app configuration will pass on any requests which are not static assets and where the URL is not recognized. The browser won't give any CORS errors because as far as it knows it's just connecting with the same Webpack server that's serving the React app.

Adding CORS Headers to the Rails API response

To be clear, if we've set up a proxy in React that's working the way we want it to, we don't need to touch Rails at all. The proxy should work great as long as the frontend and API will be on the same domain in production.

However, if we don't want to use the proxy for some reason, or if our production API is on a different domain than our React app, it's useful to know how to set up CORS headers in Rails as well.

If we're using Rails 5 and created our app with the --api flag, all we need to do is uncomment gem rack-cors in our Gemfile, then uncomment the following code in config/initializers/cors.rb:

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'localhost:3000'

    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end

Listing localhost:3000 under origins allows the frontend server at that specific URL to retrieve data from our backend, but we can change it to whatever we want. We can also add an additional allow do block beneath the first if we want to specify more than one allowed origin.

As an aside, we'd obviously want to change the backend calls in our React app to absolute rather than relative paths, since we're now calling our backend at a different origin - as the above setup has allowed us to do - rather than proxying the requests.

Cecily is a full-stack web developer based in Seattle. View her portfolio at cecilydowns.com.