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?
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.
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 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.
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.
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.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With