Implement Cross-Origin Resource Sharing:

* Add Api::ApplicationController
* Route OPTION requests (CORS preflight) to API application controller
* Filter all API requests through #cor_filter in API application
  controller
This commit is contained in:
Thibault Jouan 2012-02-26 14:10:19 +00:00
parent 88d3242843
commit 6379da88e2
6 changed files with 118 additions and 1 deletions

View File

@ -0,0 +1,14 @@
class Api::ApplicationController < ApplicationController
before_filter :cor_filter
def cor_filter
headers['Access-Control-Allow-Origin'] = request.headers['Origin']
end
def cor_preflight
headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'
headers['Access-Control-Allow-Headers'] = 'Content-Type, X-Requested-With'
head :ok
end
end

View File

@ -1,4 +1,4 @@
class Api::V0::PlaylistsController < ApplicationController
class Api::V0::PlaylistsController < Api::ApplicationController
respond_to :json
def index

View File

@ -3,6 +3,8 @@ Scube::Application.routes.draw do
namespace :v0 do
resources :playlists, :only => [:index]
end
match '*all' => 'application#cor_preflight', :via => :options
end
resources :sounds, :only => [:show]

View File

@ -0,0 +1,49 @@
require 'spec_helper'
describe Api::ApplicationController do
before do
controller.current_user = Factory.create(:user)
end
context 'CORS: Cross-Origin Ressource Sharing' do
before do
request.env['Origin'] = 'http://origin.example/'
end
context 'preflight' do
controller(Api::ApplicationController) do
alias_method :index, :cor_preflight
end
def options(action)
process action, nil, nil, nil, 'OPTIONS'
end
it 'sets Access-Control-Allow-Methods header' do
options :index
response.headers['Access-Control-Allow-Methods'].should ==
'GET, POST, PUT, DELETE'
end
it 'sets Access-Control-Allow-Methods header' do
options :index
response.headers['Access-Control-Allow-Headers'].should ==
'Content-Type, X-Requested-With'
end
end
describe 'before filter' do
controller(Api::ApplicationController) do
def index
head :ok
end
end
it 'sets Access-Control-Allow-Origin header' do
get :index
response.headers['Access-Control-Allow-Origin'].should ==
request.env['Origin']
end
end
end
end

View File

@ -0,0 +1,41 @@
require 'spec_helper'
feature 'API cross origin request' do
include UserIntegrationHelpers
let(:user) { Factory.create(:user) }
let(:origin) { 'http://origin.example/' }
background do
post sessions_path, :session => {
:email => user.email,
:password => user.password
}
end
scenario 'preflight request' do
# FIXME: replace with a more stable/generic action
# FIXME: request without redirect
request_via_redirect(
:options,
api_v0_playlists_path(:format => :json),
nil,
{ 'Origin' => origin }
)
response.headers['Access-Control-Allow-Origin'].should == origin
response.headers['Access-Control-Allow-Methods'].should ==
'GET, POST, PUT, DELETE'
response.headers['Access-Control-Allow-Headers'].should ==
'Content-Type, X-Requested-With'
end
scenario 'basic request' do
# FIXME: replace with a more stable/generic action
get api_v0_playlists_path(:format => :json), nil, {
'Origin' => origin
}
response.headers['Access-Control-Allow-Origin'].should == origin
end
end

View File

@ -0,0 +1,11 @@
require 'spec_helper'
describe '/api OPTIONS requests routing' do
it 'routes to Api::ApplicationController#cor_preflight' do
{ :options => '/api/v0' }.should route_to(
:controller => 'api/application',
:action => 'cor_preflight',
:all => 'v0'
)
end
end