问题
I have built a rails restful service that I host on Heroku and a Angular client which I am trying to run from my local machine. Eventually this client will be run added to a phonegap project. However, for now i'm testing the application in chrome and ie and my browser keeps returning the error below.
XMLHttpRequest cannot load Origin http://localhost is not allowed by Access-Control-Allow-Origin.
This is the error message that I get. I was faced with this issue before pushing to Heroku and resolved it by adding adding access headers to my responses.
after_filter :cors_set_access_control_headers
# For all responses in this controller, return the CORS access control headers.
def cors_set_access_control_headers
headers['Access-Control-Allow-Origin'] = 'http://localhost' #*
headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
headers['Access-Control-Allow-Headers'] = %w{Origin Accept Content-Type X-Requested-With X-CSRF-Token}.join(',')
headers['Access-Control-Max-Age'] = "1728000"
end
This does not seem to work. For some reason this isn't working with Heroku. Does anyone know how to solve this issue?
回答1:
One of possible solutions for Rails 4 (did not check earlier versions). I used rails-api
to create stand-alone API server. So, example based on ActionController::API
. The same solution must work fine in case of using ActionController::Base
.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::API
include ActionController::ImplicitRender
include ActionController::MimeResponds
def cors_preflight_check
headers['Access-Control-Max-Age'] = '1728000'
render json: {} # Render as you need
end
end
# config/application.rb
class Application < Rails::Application
config.action_dispatch.default_headers = {
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST, PUT, PATCH, DELETE, GET, OPTIONS',
'Access-Control-Request-Method' => '*',
'Access-Control-Allow-Headers' => 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
}
end
# config/routes.rb
# Last route definition code line
match '*path', to: 'application#cors_preflight_check', via: [:options]
This solution seems less hackish for me. Also, it takes care on OPTIONS
HTTP method in "Rails-way".
回答2:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :cors_preflight_check
after_filter :cors_set_access_control_headers
# For all responses in this controller, return the CORS access control headers.
def cors_set_access_control_headers
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
headers['Access-Control-Allow-Headers'] = %w{Origin Accept Content-Type X-Requested-With auth_token X-CSRF-Token}.join(',')
headers['Access-Control-Max-Age'] = "1728000"
end
def cors_preflight_check
if request.method == "OPTIONS"
headers['Access-Control-Allow-Origin'] = 'http://localhost'
headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
headers['Access-Control-Allow-Headers'] = %w{Origin Accept Content-Type X-Requested-With auth_token X-CSRF-Token}.join(',')
headers['Access-Control-Max-Age'] = '1728000'
render :text => '', :content_type => 'text/plain'
end
end
end
That seemed to do the trick.
回答3:
I using rails-api and this solution work for me
https://til.hashrocket.com/posts/4d7f12b213-rails-5-api-and-cors
Note: change origins 'localhost:4200' to origins '*'
来源:https://stackoverflow.com/questions/19883497/heroku-rails-cors-issue