No 'Access-Control-Allow-Origin' header is present on the requested resource? - ruby-on-rails

My bootstrap glyphicons show on other browsers, but I get this error on google chrome:
Font from origin 'http://d37p52igaahgm9.cloudfront.net' has been
blocked from loading by Cross-Origin Resource Sharing policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://www.anthonygalli.com' is therefore not
allowed access.
The error persists despite trying:
application_controller.rb
before_action :set_cors
def set_cors
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Request-Method'] = '*'
end
application.rb
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
config.action_dispatch.default_headers = {
'Access-Control-Allow-Origin' => '*',
'Access-Control-Request-Method' => '*'
}
CORS Configuration Editor
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>https://www.anthonygalli.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Content-*</AllowedHeader>
<AllowedHeader>Host</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>https://anthonygalli.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Content-*</AllowedHeader>
<AllowedHeader>Host</AllowedHeader>
</CORSRule>
</CORSConfiguration>
REFERENCES
Amazon S3 CORS (Cross-Origin Resource Sharing) and Firefox cross-domain font loading
Font from origin has been blocked from loading by Cross-Origin Resource Sharing policy

I had everything properly configured:
# config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "*"
resource "*",
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
And still I was having the error:
Access to XMLHttpRequest at 'https://playcocola.com/api/' from origin 'https://client.playcocola.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
It was happening randomly, only in production and only in some requests, not all.
The problem was related with the size of the uploaded file and my nginx configuration in production. The solution was here: CORS error upload file ~4mb
# nginx.conf
http {
[...]
client_max_body_size 50M;
}

You don't need to (shouldn't be) generating the headers in every response.
In your case, I would wager the asset request from your browser is being "preflighted" with an OPTIONS request, but the CDN passes on the request without Access-Control request headers. The CDN thus (correctly) receives no CORS response headers from your Rails app, so the browser doesn't even attempt the GET request, and fails with the Cross-Origin error.
"preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
Your CDN needs be set up to forward the correct request headers to your app server such that it knows to generate the CORS headers. Then, the CDN will pass these CORS response headers along to the browser.
When you want OPTIONS responses to be cached, configure CloudFront to forward the following headers: Origin, Access-Control-Request-Headers, and Access-Control-Request-Method.
http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html#header-caching-web-cors
If you make the change to your CDN for those headers and then invalidate your assets, your rack-cors configuration by itself should work just fine.
# config/initializers/cors.rb
# #note: must be run after initializers/_assets.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
# All asset requests should be to rails prefixed assets paths
# serverd from the asset pipeline (e.g.: "/assets/*" by default)
resource "#{Rails.application.config.assets.prefix}/*",
# Allow any request headers to be sent in the asset request
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Headers
headers: :any,
# All asset fetches should be via GET
# Support OPTIONS for pre-flight requests
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
methods: [:get, :options]
end
end

Try adding method and headers in application controller. It worked for me.
def cors_set_access_control_headers
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, PATCH, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
end

Related

AMP Access-Control-Allow-Credentials Error

I have problem After google cache my AMP page. I am implementing amp page with rails 5. Using rake-cors gem for cross-origin. Normally page working fine but after the cache is shown console error.
Error:
The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. Origin 'https://www-myurl-in.cdn.ampproject.org' is therefore not allowed access.
config/application.rb
config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'https://www-myurl-in.cdn.ampproject.org'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
I don't know where I change in my code, Please help me.
After modifying Response Header its working fine.
response.headers['AMP-Redirect-To'] = request.protocol+request.host_with_port+url
response.headers['Access-Control-Expose-Headers'] = 'AMP-Redirect-To, AMP-Access-Control-Allow-Source-Origin'
response.headers['AMP-Access-Control-Allow-Source-Origin'] = params[:__amp_source_origin]

rack-cors failing on production build

I have an Rails 5 API project and I'm using rack-cors.
Situation:
I have some static JSON files in public/files folder, like this:
{
"example": "123456"
...
}
I can access them perfectly (from Angular client) in development, but it doesn't work in production.
In production, I'm getting the common error:
XMLHttpRequest cannot load
https://myhost.com/files/my_file.json. No
'Access-Control-Allow-Origin' header is present on the requested
resource.
The most stranger thing is that I can access the url (https://myhost.com/files/my_file.json) manually in browser without any problems.
Actual configuration:
config/initializers/cors.rb:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins my_origins
resource '*',
expose: ['awesome_token'],
headers: :any,
methods: %i[delete get head options patch post put]
end
end
Possible configuration:
So after some research, I found the following:
environments/production.rb:
# Added the following
config.public_file_server.enabled = true
cors.rb:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins my_origins
resource '*',
expose: ['awesome_token'],
headers: :any,
methods: %i[delete get head options patch post put]
end
end
# Added the following
Rails.application.config.middleware.insert_before ActionDispatch::Static, Rack::Cors do
allow do
origins '*'
resource '*',
headers: :any,
methods: %i[delete get head options patch post put]
end
end
But it make absolutely no difference.
So, my question is: Is there something that I'm missing? What's wrong?
PS: Every request is working fine, the problem is with this static JSON files in public/files folder (in production build).

Allow CORS in Ruby on Rails

In my config/application.rb file, I have this code,
config.action_dispatch.default_headers = {
'Access-Control-Allow-Origin' => '*',
'Access-Control-Request-Method' => 'GET, PATCH, PUT, POST, OPTIONS, DELETE'
}
But that does not allow me to send a post request to a route on my sever
Safari gives this error:
http://localhost:3000/studentsFailed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:3000/studentsFailed to load resource: Origin http://localhost:4200 is not allowed by Access-Control-Allow-Origin.
localhost:1XMLHttpRequest cannot load http://localhost:3000/students. Origin http://localhost:4200 is not allowed by Access-Control-Allow-Origi
And in my Rails server console:
Started OPTIONS "/students" for ::1 at 2015-03-28 21:00:45 -0500
ActionController::RoutingError (No route matches [OPTIONS] "/students"):
I spent some time working on this and I can tell you the most reliable solution is to use rack-cors. see: https://github.com/cyu/rack-cors
First add the gem:
gem 'rack-cors', '~> 0.3.1'
then in application.rb add
config.middleware.insert_before ActionDispatch::Static, Rack::Cors do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
If your production app does not serve static assets (such as if you use a serve like nginx or apache), consider replacing ActionDispatch::Static in the above example with 0. See https://github.com/cyu/rack-cors#common-gotchas for more information about the argument.
I was able to figure this out with a bit of help from #Akiomi's answer:
In my routes.rb, I added the following code to the top of the file:
match '(:anything)' => 'application#nothing', via: [:options]
Next, in my application controller, I added:
def nothing
render text: '', content_type: 'text/plain'
end
Along with the headers in config/application.rb:
config.action_dispatch.default_headers = {
'Access-Control-Allow-Origin' => '*',
'Access-Control-Request-Method' => 'GET, PATCH, PUT, POST, OPTIONS, DELETE',
'Access-Control-Allow-Headers:' => 'Origin, X-Requested-With, Content-Type, Accept'
}
Yes, notice the 'Access-Control-Allow-Headers:' => 'Origin, X-Requested-With, Content-Type, Accept' that was not included in my original question, this is one of the big problems.
Add the following code:
In config/routes.rb:
match 'students' => 'students#option', via: [:options]
In controllers/student_controller.rb:
def option
render text: '', content_type: 'text/plain'
end
Or you can use rack-cors.
In some cases a browser will do a preflight request: rather than actually doing the request it first does an OPTIONS request to the same url, so that it can find out what the values of the various CORS headers are (More on preflighting here). If this request is successful and the headers have the correct values, it then does the actual request.
You haven't added a route for these options requests, so they're going through to the rails 404 page which doesn't include the CORS headers.
The OPTIONS response just needs to set the same CORS headers as you would normally set during a request. It shouldn't do anything else. For example
match 'students' => 'students#cors_preflight', via: [:options]
def cors_preflight
render nothing: true
end
Note that there are other CORS headers you may need to set such as Access-Control-Allow-Credentials, Access-Control-Allow-Headers
When you've got this working you may wish to consider tightening this up a little - you are potentially opening your app to cross site scripting attacks.
Rails 5
config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :post, :options]
end
end

CORS issue using Grape API and Heroku

I have a read-only API and it works well locally with a Vagrant setup. Live on my Heroku app, every API request is denied due to a CORS error: "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access."
In my API's base class, I have the following to set the headers:
module API
class Base < Grape::API
before do
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
end
mount API::V1::Base
end
end
I suspect that this before call is not being fired—if I use a puts statement inside of it, that statement does not appear in my console with the rest of the output.
I am at a loss. Hopefully someone has some experience with this. Thank you.
Edit: I have also followed Grape's CORS instructions but get the same result.
Success. I used the rack-cors gem and the following:
#application.rb
config.middleware.use Rack::Cors do
allow do
origins '*'
# location of your API
resource '/api/*', :headers => :any, :methods => [:get, :post, :options, :put]
end
end
You get Access-Control-Allow-Origin error every time you made a request.
This is probably because your server API does not respond to OPTIONS requests with the headers required for CORS.
You can check it in the development console -> network tab if you are using Google Chrome.
It's interesting that some Javascript frameworks do make an OPTIONS request before a normal request is sent to the server.
Solution:
Modify your Gemfile to include 'rack-cors'.
Run bundle install
Modify your config.ru:
*if you get errors launching rails server, check your API namespace after 'run'
require 'rack/cors'
use Rack::Cors do
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :post, :options, :put]
end
end
run API::V1::Base
Now you should see Grape handles all OPTIONS requests with the CORS headers.

Strophe-Ejabberd-Rails: Access-Control-Allow-Origin Error

I am getting the CORS error while trying to connect xmpp server, ejabberd running on port 5280 using Strophe on Rails app.
XMLHttpRequest cannot load http://localhost:5280/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
I tried the following ways to resolve the issue.
=> enabled cors for all domains in application.rb
config.middleware.use Rack::Cors do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
=> Added strophe.flxhr.min.js but it gave another error flensed is not
defined, which I wasn't able to resolve.
How to resolve this error.
Changing http://localhost:5280/ to http://localhost:5280/http-bind resolves the issue.

Resources