Connecting Frontend to Backend: Rails Rack CORS
Recently, I’ve been building an application that requires me to connect a React frontend to a Rails backend. The backend was pulling in data from an external API and I wanted to be able to fetch that data via AJAX to render on my frontend. One of the tools I used to accomplish this task was Rack-CORS, a popular Rails middleware option. However, I unknowingly configured it incorrectly, which cause me to spend hours debugging issues that could have been prevented much earlier.
For that reason, I want to break down what Rack CORS does, why it’s useful, and how to configure it on setup — ensuring I don’t run into the same problem again in the future.
So…what is Rack CORS?
Let’s go to the source:
"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."--- Rack CORS Documentation
Cross-Origin Resource Sharing (CORS) is a browser policy that allows us to permit an external source — or origin — to retrieve data from our resource. This is the opposite of the Same-Origin Policy (SOP) which only allows access to resources that come from the same origin as the rest of the application — typically for security reasons.
For example, let’s say my backend is providing API data on localhost:3000/ and my frontend runs on localhost:3001/. CORS allows me to assign an origin of localhost:3001/, which will permit my frontend to access the JSON data rendered in my API. But any other servers that would attempt to do the same would be unable to.
Rack CORS is a Ruby Gem that gives us the ability to, simply put, utilize Cross-Origin Resource Sharing with any Rack compatible web application. If I’ve set up a button on my React frontend that sends a fetch request to retrieve data from my Rails backend, Rack CORS tells Rails that it is safe to send the data to that source. You get to determine which resources can access that information.
To set up Rack CORS we want to make sure the Gem is install in our Gemfile.
## In Gemfile...gem 'rack-cors'## ...or in Terminal.gem install rack-cors
If your Rails app is set up using typical Rails convention, you’ll next want to access the cors.rb file, which can typically be found in the config/initializers directory. With Rack CORS installed, you should find a bunch of commented out text. All you need to do is comment the following bit back in.
Rails.application.config.middleware.insert_before 0, Rack::Cors do
methods: [:get, :post]
With this code implemented, you’re ready to start making fetch requests from your frontend to your backend. However, there’s a couple things to be aware of before you get started.
Our origins should be followed by a string that includes the domain of the source we want to have access to our backend data. In my previous example, that would be http://localhost:3001/. Keep in mind that this domain must include a protocol, a domain and a port for it to function correctly. You can also complete this section with an asterisk (*), but this will allow any external source to access your backend, which can result in security issues — so use it carefully.
However, Rack CORS offers us even more control. You can indicate a specific resource path that you want the frontend to be able to access, such as /users, /games, /characters, etc — depending on how your routing is set up. You can also provide HTTP headers that you want to allow to be provided cross-resource, as well as which REST methods are permitted to be used. In the case of our current example, I only allow GET and POST requests. A user could not edit or delete data from the API.
With Rack CORS correctly implemented, I can easily fetch the information I require from the backend to make the frontend do its magic. It is a valuable tool for secure communication across resources.