So there are a handful of questions on StackOverflow addressing this error, but of the 10-15 I checked, I could not find a solution to my exact problem.
I am running an Angular app (port 9000) and a Rails app (port 3000) on a remote server. The angular app sends requests to the rails app via a post request.
When a request is made, the Javascript console shows this error message:
XMLHttpRequest cannot load http://0.0.0.0:3000/api/query. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://10.241.16.159:9000' is therefore not allowed access.
From what I've read, I need to change something about my Rails app so that it can accept connection from other servers (which seems odd because both apps are running on the same ec2 instance).
I've tried adding a line like
skip_before_filter :verify_authenticity_token
to my controller in rails, but this seems to have no effect.
How can I resolve this error?
In app/controllers/application_controller.rb:
before_filter :add_allow_credentials_headers
def add_allow_credentials_headers
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#section_5
#
# Because we want our front-end to send cookies to allow the API to be authenticated
# (using 'withCredentials' in the XMLHttpRequest), we need to add some headers so
# the browser will not reject the response
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 config/routes.rb:
match '*any' => 'application#options', :via => [:options]
Note, this is responding to OPTIONS requests which you will need if your Angular front-end is performing POST requests. The bit I am doing with Access-Control-Allow-Credentials is for my app so cookies are sent from the front-end.
I highly suggest that you read the docs in that mozilla link in my code above. It has a very thorough explanation of CORS. You may find that the code above is too permissive for your purposes.
In case you've not read up about it yet, let me give you some idea as to what the issue is...
You've got a problem with the CORS policy of your apps
--
CORS (Corss Origin Resource Sharing)
When you access an endpoint
on another server with XHR (XML HTTP REQUEST), your application (although I'm not sure how) will by default DENY access to the requesting resource.
The reason why this happens is to ensure only certain data / resources are made available via XHR, and is why it's used mainly for the likes of APIs.
--
rack-CORS
Anyway, you need to allow access to your Java application inside your Rails application - which I personally would recommend with the rack-CORS
gem:
#Gemfile
gem 'rack-cors'
#config/application.rb
config.middleware.use Rack::Cors do
allow do
origins '*'
resource 'api/jquery', :headers => :any, :methods => [:get, :post]
end
end
This will "allow" the requests from your different applications, fixing the issue for you.
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