2015-03-29 12 views
8

Nel mio file config/application.rb, ho questo codice,Consenti CORS in Ruby on Rails

config.action_dispatch.default_headers = { 
     'Access-Control-Allow-Origin' => '*', 
     'Access-Control-Request-Method' => 'GET, PATCH, PUT, POST, OPTIONS, DELETE' 
    } 

Ma questo non mi permette di inviare una richiesta di post per un percorso sul mio sever

Safari dà a questo errore:

http://localhost:3000/studentsFailed to load resource: the server responded with a status of 404 (Not Found) 
http://localhost:3000/studentsFailed to load resource: Origin http://localhost:4200 is not allowed by Access-Control-Allow-Origin. 
localhost:1XMLHttpRequest cannot load http://localhost:3000/students. Origin http://localhost:4200 is not allowed by Access-Control-Allow-Origi 

E nella mia console del server Rails:

Started OPTIONS "/students" for ::1 at 2015-03-28 21:00:45 -0500 

ActionController::RoutingError (No route matches [OPTIONS] "/students"): 

risposta

13

Ho trascorso un po 'di tempo a lavorare su questo e posso dire che la soluzione più affidabile è usare rack-cors.vedi: https://github.com/cyu/rack-cors

Prima aggiungere la gemma:

gem 'rack-cors', '~> 0.3.1' 

poi nel application.rb aggiungere

config.middleware.insert_before 0, "Rack::Cors" do 
    allow do 
    origins '*' 
    resource '*', :headers => :any, :methods => [:get, :post, :options] 
    end 
end 
+0

questo dovrebbe funzionare. io uso 'ActionDispatch :: Static' come primo argomento invece di' 0'. –

+0

Questo ha funzionato molto bene per me. @ReydiSutandang, perché hai suggerito 'ActionDispatch :: Static' invece di' 0'? – andreshg112

+0

Ora che ho lavorato con un nuovo progetto, ho notato che questa soluzione ha molto senso per esigenze più complesse. L'ho selezionato come risposta migliore –

1

aggiungere il seguente codice:

In config/routes.rb:

match 'students' => 'students#option', via: [:options] 

In controllers/student_controller.rb:

def option 
    render text: '', content_type: 'text/plain' 
end 

oppure è possibile utilizzare rack-cors.

+0

Non funziona .. –

+0

Ho trovato un modo per usarlo, grazie! –

3

sono stato in grado di capire questo fuori con un po 'di aiuto da parte @ risposta di Akiomi:

Nel mio routes.rb, ho aggiunto il seguente codice all'inizio del file:

match '(:anything)' => 'application#nothing', via: [:options] 

Avanti, nel mio controller applicazione, ho aggiunto:

def nothing 
    render text: '', content_type: 'text/plain' 
end 

Insieme con le intestazioni in config/application.rb:

config.action_dispatch.default_headers = { 
    'Access-Control-Allow-Origin' => '*', 
    'Access-Control-Request-Method' => 'GET, PATCH, PUT, POST, OPTIONS, DELETE', 
    'Access-Control-Allow-Headers:' => 'Origin, X-Requested-With, Content-Type, Accept' 
} 

Sì, notare lo 'Access-Control-Allow-Headers:' => 'Origin, X-Requested-With, Content-Type, Accept' che non era incluso nella mia domanda originale, questo è uno dei grandi problemi.

0

In alcuni casi, un browser eseguirà una richiesta di verifica preliminare: anziché effettuare effettivamente la richiesta, per prima cosa esegue una richiesta OPTIONS allo stesso URL, in modo che possa scoprire quali sono i valori delle varie intestazioni CORS. preflight here). Se questa richiesta ha esito positivo e le intestazioni hanno i valori corretti, allora fa la richiesta effettiva.

Non hai aggiunto un percorso per queste richieste di opzioni, quindi stanno passando alla pagina 404 dei binari che non include le intestazioni CORS.

La risposta OPTIONS ha solo bisogno di impostare le stesse intestazioni CORS come si regolerebbero normalmente durante una richiesta. Non dovrebbe fare nient'altro. Per esempio

match 'students' => 'students#cors_preflight', via: [:options] 

def cors_preflight 
    render nothing: true 
end 

noti che ci sono altre intestazioni CORS potrebbe essere necessario impostare quali Access-Control-Allow-Credentials, Access-Control-Allow-Headers

Quando hai questo lavoro si può prendere in considerazione questo inasprimento un po '- si è potenzialmente aprendo la tua app agli attacchi cross-site scripting.

+0

È un'API pubblica. Sapevo della 404, ma non funziona perché non hai ancora incluso le intestazioni. Di seguito ho risposto alla mia domanda in un modo che funziona. –

0

è possibile consentire origini da application_controller

class ApplicationController < ActionController::Base 
    before_action :allow_cross_domain_ajax 
    def allow_cross_domain_ajax 
     headers['Access-Control-Allow-Origin'] = '*' 
     headers['Access-Control-Request-Method'] = 'POST, OPTIONS' 
    end 
end