Cross-Origin Resource Sharing(CORS)
GET request
When you try to GET data from another website, your browser's console will tell you: No ‘Access-Control-Allow-Origin’ header is present on the requested resource...
You could just simply paste the following code snippet onto your desired controller, then it should work: CORS in Rails
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-Max-Age'] = "1728000"
end
# If this is a preflight OPTIONS request, then short-circuit the
# request, return only the necessary headers and return an empty
# text/plain.
def cors_preflight_check
if request.method == :options
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
headers['Access-Control-Allow-Headers'] = 'X-Requested-With, X-Prototype-Version'
headers['Access-Control-Max-Age'] = '1728000'
render :text => '', :content_type => 'text/plain'
end
end
We can also put these two methods onto ApplicationController and invoke them in the desired controllers :
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
# http://www.tsheffler.com/blog/2011/02/22/cross-origin-resource-sharing-for-json-and-rails/
# 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-Max-Age'] = "1728000"
end
# If this is a preflight OPTIONS request, then short-circuit the
# request, return only the necessary headers and return an empty
# text/plain.
def cors_preflight_check
if request.method == :options
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
headers['Access-Control-Allow-Headers'] = 'X-Requested-With, X-Prototype-Version'
headers['Access-Control-Max-Age'] = '1728000'
render :text => '', :content_type => 'text/plain'
end
end
end
POST request
You need to add and modify something on your routes.rb, application_controller.rb and related controller.
routes.rb
match '/:api_options_request' => "application#index", via: :options, :constraints => {:api_options_request => /.*/}
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
skip_before_filter :verify_authenticity_token, only:[:index]
before_filter :set_headers, only:[:index]
# http://www.tsheffler.com/blog/2011/02/22/cross-origin-resource-sharing-for-json-and-rails/
# 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-Max-Age'] = "1728000"
end
# If this is a preflight OPTIONS request, then short-circuit the
# request, return only the necessary headers and return an empty
# text/plain.
def cors_preflight_check
if request.method == :options
puts "cors_preflight_check"
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
headers['Access-Control-Allow-Headers'] = 'X-Requested-With, X-Prototype-Version'
headers['Access-Control-Max-Age'] = '1728000'
render :text => '', :content_type => 'text/plain'
end
end
#http://stackoverflow.com/questions/19772852/sending-an-angular-post-request-with-parameter-to-rails-api
def index
puts "Do nothing."
render nothing: true
end
def set_headers
if request.headers["HTTP_ORIGIN"]
puts 'ApplicationController.set_headers'
# better way check origin
# if request.headers["HTTP_ORIGIN"] && /^https?:\/\/(.*)\.some\.site\.com$/i.match(request.headers["HTTP_ORIGIN"])
headers['Access-Control-Allow-Origin'] = request.headers["HTTP_ORIGIN"]
headers['Access-Control-Expose-Headers'] = 'ETag'
headers['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE, OPTIONS, HEAD'
headers['Access-Control-Allow-Headers'] = '*,x-requested-with,Content-Type,If-Modified-Since,If-None-Match,Auth-User-Token'
headers['Access-Control-Max-Age'] = '86400'
headers['Access-Control-Allow-Credentials'] = 'true'
end
end
end
WHATEVER_controller.rb
class MessagesController < ApplicationController
respond_to :json
skip_before_filter :verify_authenticity_token
before_filter :cors_preflight_check
after_filter :cors_set_access_control_headers
def index
respond_with Message.all
end
def show
respond_with Message.find(params[:id])
end
def create
respond_with Message.create(message_params)
end
def update
respond_with Message.update(params[:id], params[:message])
end
def destroy
respond_with Message.destroy(params[:id])
end
protected
def message_params
params.require(:message).permit(:title, :sender, :numbers, :email, :content)
end
end
rack-cors save my life!
Let rack-cors handle CORS.
Gemfile
gem 'rack-cors', :require => 'rack/cors'
application.rb
config.middleware.insert_before 0, "Rack::Cors", :debug => true, :logger => (-> { Rails.logger }) do
allow do
origins '*'
resource '*',
:headers => :any,
:methods => [:get, :post, :delete, :put, :options, :head],
:max_age => 0
end
end
WHATEVERS_controller.rb
class MessagesController < ApplicationController
respond_to :json
skip_before_filter :verify_authenticity_token
def index
respond_with Message.all
end
def show
respond_with Message.find(params[:id])
end
def create
respond_with Message.create(message_params)
end
def update
respond_with Message.update(params[:id], params[:message])
end
def destroy
respond_with Message.destroy(params[:id])
end
protected
def message_params
params.require(:message).permit(:title, :sender, :numbers, :email, :content)
end
end