Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access-Control-Allow-Origin on a single Rails route

In my Rails app, I'm building a feature that allows users to embed data from the app on other sites using a Javascript snippet.

My Javascript snippet makes a GET request to a route in my rails app that returns raw JSON. When snippet and the JSON share the same domain, everything works well, but I'm running into CORS issues when I embed the snippet on another site.

Using the solution I found here, I've begun configuring my Rails app for CORS.

In my application_controller.rb:

before_filter :add_allow_credentials_headers

def add_allow_credentials_headers
    response.headers['Access-Control-Allow-Origin'] = request.headers['Origin'] || '*'   
    response.headers['Access-Control-Allow-Credentials'] = 'true'
end 

def options
    head :status => 200, :'Access-Control-Allow-Headers' => 'accept, content-type'
end

In my routes.rb:

get 'embed_json' => 'application#options', :via => [:options]

However, when I hit the above route in my browser, the app no longer returns the JSON object—just a blank screen.

There seem to be a number of conflicting approaches on how best to handle CORS on a single Rails route. Is there a "Rails way" to handle this requirement?

like image 860
Cameron Scott Avatar asked Aug 20 '16 15:08

Cameron Scott


People also ask

How do I enable CORS in Rails?

Using rack-cors You need to inform Rails which origin it should allow. To do that, you need to create a new initializer for your application. This configuration will only allow HTTP POST calls to /order endpoint and all HTTP methods to any other endpoint. You need to pay close attention to the origins parameter.

Can Access Control allow origin have wildcard?

For requests without credentials, the literal value " * " can be specified as a wildcard; the value tells browsers to allow requesting code from any origin to access the resource. Attempting to use the wildcard with credentials results in an error. Specifies an origin. Only a single origin can be specified.

What is allow access allow origin?

What is the Access-Control-Allow-Origin response header? The Access-Control-Allow-Origin header is included in the response from one website to a request originating from another website, and identifies the permitted origin of the request.

What is rack Cors in Rails?

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.


3 Answers

A call to head won't return JSON by definition. The options hash, when you call it with head will be converted into headers.

Might try this instead, an options call will give the headers as needed with an empty response body. A call to index should render JSON, along with the headers you set in the add_allow_credentials_headers filter.

def add_allow_credentials_headers
  response.headers['Access-Control-Allow-Origin'] = request.headers['Origin'] || '*'   
  response.headers['Access-Control-Allow-Credentials'] = 'true'
  response.headers['Access-Control-Allow-Headers'] = 'accept, content-type'
end 

def options
  head :ok
end

def index
  # do something here that renders a JSON response
end

Also, another option for enabling CORS on your rails app is rack-cors, might do what you need without the hassle of doing it yourself.

like image 80
Jeff Wigal Avatar answered Sep 21 '22 17:09

Jeff Wigal


Add status: :ok to the raw JSON you are returning. In case you return an empty body, add head :ok to return a 200 status

To only enable CORS for options method, what you can do is:

before_filter :add_allow_credentials_headers, only: [:options]

def add_allow_credentials_headers
  response.headers['Access-Control-Allow-Origin'] = request.headers['Origin'] || '*' # the domain you're making the request from
  response.headers['Access-Control-Allow-Credentials'] = 'true'
  response.headers['Access-Control-Allow-Headers'] = 'accept, content-type'
end 

def options
  # your json response here or just 'head :ok' if empty 200 response
end
like image 37
tekina Avatar answered Sep 20 '22 17:09

tekina


Install this gem:

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

Then add this to your config/application.rb file.

module YourApp
  class Application < Rails::Application

    # ...

    # Rails 3/4

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

    # Rails 5

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

  end
end

this will do the trick read more. Cors

like image 39
Alex Onozor Avatar answered Sep 18 '22 17:09

Alex Onozor