2015-03-29 3 views
8

In meiner config/application.rb Datei, ich diesen Code haben,zulassen CORS in Ruby on Rails

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

Aber das erlaubt mir nicht, auf meinem Sever

Safari ergibt dies eine Post-Anforderung an eine Route zu schicken Fehler:

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 

Und in meiner Rails-Server-Konsole:

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

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

Antwort

13

Ich habe einige Zeit damit verbracht, und ich kann Ihnen sagen, die zuverlässigste Lösung ist Rack-Cors zu verwenden.siehe: https://github.com/cyu/rack-cors

zuerst die Perle hinzu:

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

dann in application.rb hinzufügen

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

sollte dies funktionieren. Ich verwende 'ActionDispatch :: Static' als erstes Argument anstelle von' 0'. –

+0

Das hat sehr gut für mich funktioniert. @ReydiSutandang, Warum hast du "ActionDispatch :: Static" anstelle von "0" vorgeschlagen? – andreshg112

+0

Jetzt, wo ich mit einem neuen Projekt gearbeitet habe, habe ich bemerkt, dass diese Lösung sehr sinnvoll für kompliziertere Bedürfnisse ist. Ich habe es als die beste Antwort gewählt –

1

Fügen Sie den folgenden Code:

In config/routes.rb:

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

In controllers/student_controller.rb:

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

Oder Sie können rack-cors verwenden.

+0

nicht funktioniert .. –

+0

Einen Weg gefunden, dies zu benutzen, danke! –

3

Ich konnte dies mit ein wenig Hilfe, um herauszufinden, von @ Akiomi Antwort:

In meinem routes.rb, ich den folgenden Code am Anfang der Datei hinzugefügt:

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

Als nächstes in meiner Anwendung Controller, fügte ich hinzu:

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

Zusammen mit den Headern in config/application.rb:

Ja, beachten Sie die 'Access-Control-Allow-Headers:' => 'Origin, X-Requested-With, Content-Type, Accept', die nicht in meiner ursprünglichen Frage enthalten war, das ist eines der großen Probleme.

0

In einigen Fällen führt ein Browser eine Preflight-Anfrage durch: Anstatt die Anfrage zu machen, führt er zunächst eine OPTIONS-Anfrage an dieselbe URL durch, um herauszufinden, welche Werte die verschiedenen CORS-Header haben Preflight here). Wenn diese Anfrage erfolgreich ist und die Header die richtigen Werte haben, führt sie die eigentliche Anfrage durch.

Sie haben keine Route für diese Optionenanforderungen hinzugefügt, also gehen sie zur Seite rails 404, die die CORS-Header nicht enthält.

Die OPTIONS-Antwort muss nur dieselben CORS-Header festlegen, die Sie normalerweise während einer Anforderung festlegen würden. Es sollte nichts anderes tun. Zum Beispiel

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

def cors_preflight 
    render nothing: true 
end 

Hinweis, dass es andere CORS-Header Sie festlegen, wie Access-Control-Allow-Credentials benötigen, Access-Control-Allow-Headers

Wenn Sie dies haben arbeiten Sie ein wenig Straffung dies bis betrachten können wollen - Sie sind Öffnen Sie Ihre App möglicherweise, um Site-Scripting-Angriffe zu umgehen.

+0

Es ist eine öffentliche API. Ich wusste von der 404, aber das funktioniert nicht, da Sie noch keine Header hinzugefügt haben. Im Folgenden habe ich meine Frage so beantwortet, dass sie funktioniert. –

0

Sie erlauben Ursprünge von 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