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

Reference

results matching ""

    No results matching ""