2

I'm having trouble setting up CORS with my Rails API in CloudAnywhere.

I am trying to set up a React front end and a Rails back end in two separate CloudAnywhere containers. (Let's call them rails.codeanyapp.com and react.codeanyapp.com.)

The React front end is set up with a proxy to Rails (i.e., "proxy": "https://rails.codeanyapp.com" in package.json).

The Rails back end has the following code in config/initializers/cors.rb

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'https://react.codeanyapp.com/'

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

GET requests work fine. However, when I do a POST, I get the following error in Rails

Started POST "/authors.json" for 104.42.117.130 at 2019-03-19 13:05:52 -0400
Cannot render console from 104.42.117.130! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by AuthorsController#create as JSON
  Parameters: {"fname"=>"James", "lname"=>"madison", "email"=>"james@madison.com", "author"=>{"fname"=>"James", "lname"=>"madison", "email"=>"james@madison.com"}}
HTTP Origin header (https://rails.codeanyapp.com) didn't match request.base_url (https://react.codeanyapp.com)
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)

Notice that CodeAnywhere is set up so the public URL is https://rails.codeanyapp.com even though the server is actually running on port 3000. I suspect the issue is on the Rails side when the incoming port is "forwarded" to 3000; but, I don't think I have privileges to modify that behavior.

Notice also that both the Origin and the base are https. (Most other posts about this problem are when one is http and the other is https.)

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Zack
  • 6,232
  • 8
  • 38
  • 68

1 Answers1

0

The main problem is that I got lazy and tried to simply throw json rendering into an existing controller. (Specifically, I added a respond_to block to an existing controller that is a subclass of ApplicationController.) The problem with this is that, by default, Rails adds CSRF and other middleware that doesn't apply as cleanly to an API.

The correct solution is to create a separate controller that inherits from ApplicationController::API Combining API and web views in Rails 5

The quick and dirty solution was to turn off CSRF for API calls by adding protect_from_forgery unless: -> { request.format.json? } to application_controller.rb

Zack
  • 6,232
  • 8
  • 38
  • 68