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.
Related
I am out of ideas. I made a small app for a friend who is using it in a school. As long as it is on non-school internet, it works fine. At school, though, there are two buttons that don't work. They both are making an ajax request to a different controller. They give a no access-control-allow-origin header error. I have tried every fix that I can find, and nothing will work. I am out of ideas. The current iteration involves the rack-cors gem, which I have below. I have also tried the fixes at
CORS issue: Getting error "No 'Access-Control-Allow-Origin' header is present" when it actually is, XMLHttpRequest No 'Access-Control-Allow-Origin' header is present on the requested resource, http://www.yihangho.com/rails-cross-origin-resource-sharing/, and http://leopard.in.ua/2012/07/08/using-cors-with-rails/. Is there anything else I can do?
config.ru
require 'rack/cors'
use Rack::Cors do
allow do
origins '*'
resource '*',
:headers => :any,
:methods => [:get, :post, :delete, :put, :options, :patch]
end
end
application.rb
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :post, :patch, :options, :put]
end
end
CORS is designed to prevent cross domain XML requests.
I'm not sure as to the specific reasons for this, but the short of it is that if you try and hit an external domain with Ajax (without CORS permissions granted), it will be denied.
As long as it is on non-school internet, it works fine
Yep, because the "domain" will be considered "local" Sorry I misread that as "Intranet".
This will depend on the server you're accessing - you need to make sure the server has CORS enabled.
I've dealt with a similar issue to you before.
You've done the right thing by using rack-cors:
#config/application.rb
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*' #-> has to be "*" or specific
resource '*', headers: :any, methods: [:get, :post, :options]
end
end
If you're using this (remember, you have to restart your server to get it working), it should work.
The main considerations for CORS are the origin and resource - they either have to be "*" (all), or explicitly defined (IE google.com or something).
In your case, allowing them "all" should be okay to test - you'll then need to ensure you have the specific domain defined.
(sorry for bad english)
I try to execute an ajax request but it doesn't work due to same-origin policy. My application is not deployed yet and I use Ruby on Rails 3.2.3 with Unicorn server.
The AJAX request is in an asset javascript file and I call it in a view. when I try to get the datas from the AJAX requests, the console says
"Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at [url]. This can be fixed by moving the resource to the same domain or enabling CORS."
I tried everything :
Use jsonp in ajax request : console.log said syntax error
Use rack cors, with making everything said on the readme (https://github.com/cyu/rack-cors), but it didn't work, still the same message in the console (restatring server or not)
Try some syntaxes for rack-cors said on every post about it in stack overflow I could find, I tried this :
application.rb :
config.middleware.insert_before ActionDispatch::Static, Rack::Cors do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options], expose: :location
end
but it didn't work, and I tried this in config.ru
use Rack::Cors do
# allow all origins in development
allow do
origins 'localhost:3000'
resource '*',
:headers => :any,
:methods => [:get, :post, :delete, :put, :options]
end
end
I tried this code with "origins 'localhost:3000'" ans with "origins '*'" but none of them worked, I didn't forgot the "require 'rack/cors'"
I am desperte, could you help me please ?
It is almost undoubtedly that you aren't defining the proper headers to allow access. The following walk-through should get you going:
http://dotnet-concept.com/Tip/2015/3/5798824/Cross-Origin-Request-Blocked-The-Same-Origin-Policy-disallows-reading-the-remote-resource-This-can-be-fixed-by-moving-the-resource-to-the-same-domain-or-enabling-CORS-
We had a similar situation that was resolved using rack-cors
Gemefile:
gem 'rack-cors', :require => 'rack/cors'
application.rb:
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
Don't forget to restart your rails server!
EDIT:
It just occurred to me, that this will only work in production if you are using your app server as the web server as well. If you are using Nginx or Apache as your web server, then your static assets will be served from it. You will have to enable CORS on Nginx/Apache.
Every time I'm trying to set the 'Access-Control-Allow-Origin' header for the Spree Commerce API, no header is being passed for Ajax calls.
I'm currently extending the base_controller.rb:
File: app/controllers/spree/api/base_controller_decorator.rb
after_filter :set_access_control_headers
def set_access_control_headers
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Request-Method'] = '*'
end
The header is added to the requests every time I view a JSON directly from the browser. However, no header is visible when making AJAX calls...
Can anybody explain me how to do this? Is there a workaround for this issue?
You don't need anything in your application controller, rather you need a gem:
Add gem 'rack-cors', :require => 'rack/cors' to your Gemfile, then bundle install
In config/application.rb configure rack-cors to accept requests from any origin. It belongs anywhere inside the Application class.
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
origins '*' indicates you are allowing requests from any domain. If you want to restrict to a specific domain (i.e. internally open an api, but keep it closed to external users), change '*' to the specific domain name.
see https://github.com/cyu/rack-cors for more details
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
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.