2016-02-07 15 views
5

ich einen einfachen Tornado-Server habe, die die Klasse hat:Tornado-Server: enable CORS fordert

class BaseHandler(tornado.web.RequestHandler): 
    def set_default_headers(self): 
     print "setting headers!!!" 
     self.set_header("Access-Control-Allow-Origin", "*") 

Wenn ein regelmäßiger (kein CORS) Antrag gestellt wird, antwortet der Server wie erwartet, einschließlich dem Access-Control- Allow-Origin-Kopfzeile Wenn ich jedoch eine Postanforderung von einer anderen Domäne (mit jQuery.post) erstelle, lautet die Antwort 404 und ein Fehler wird angezeigt: "XMLHttpRequest kann nicht geladen werden http://dev-machine:8090/handshake. Auf der angeforderten Ressource ist kein Header" Access-Control-Allow-Origin "vorhanden. Origin 'http://localhost:8090' ist daher kein Zugriff erlaubt. Die Antwort hatte den HTTP-Statuscode 404. "

Können Sie sagen, ob ich etwas vermisse? (ein anderer Header/andere Konfiguration/irgendetwas anderes)

+0

dass' pass' es überflüssig/falsch ist –

Antwort

21

Ihr Code fehlt Preflight, die OPTIONS Anfrage.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS:

Die Cross-Origin Resource Sharing Standardwerke durch neue HTTP Header hinzufügen, die Server erlauben den Satz von Herkunft zu beschreiben, sind erlaubt, dass Informationen über einen Web-Browser zu lesen. Zusätzlich für HTTP-Request-Methoden, die Nebenwirkungen auf Benutzerdaten (in insbesondere für andere HTTP-Methoden als GET, oder für POST-Verwendung mit bestimmten MIME-Typen) verursachen können, fordert die Spezifikation, dass Browser die Anfrage "Preflight" Erwerben von unterstützten Methoden vom Server mit einer HTTP-OPTIONS-Anfrage-Methode, und dann, nach "Genehmigung" von der Server, Senden der tatsächlichen Anfrage mit der eigentlichen HTTP-Anfrage Methode. Server können Clients auch darüber informieren, ob "Anmeldeinformationen" (einschließlich Cookies und HTTP-Authentifizierungsdaten) mit Anfragen gesendet werden sollen.

Um den Preflight-Handler zu implementieren, fügen Sie einfach den options-Handler mit den gleichen Kopfzeilen und ohne Text hinzu.

class BaseHandler(tornado.web.RequestHandler): 

    def set_default_headers(self): 
     print "setting headers!!!" 
     self.set_header("Access-Control-Allow-Origin", "*") 
     self.set_header("Access-Control-Allow-Headers", "x-requested-with") 
     self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS') 

    def post(self): 
     self.write('some post') 

    def get(self): 
     self.write('some get') 

    def options(self): 
     # no body 
     self.set_status(204) 
     self.finish() 

bearbeiten

I x-requested-with Header erlaubt Liste hinzugefügt haben. Und hier ist einfach jquery Beispiel:

$.ajax({ 
    url: "http://some_tornado/api", 
    type: "POST", 
    crossDomain: true, 
    data: 'some_data', 
    success: function (response) { 
    alert(response); 
    }, 
    error: function (xhr, status) { 
    alert("error"); 
    } 
}); 

und einige wirklich gute Artikel über cors - http://dev.housetrip.com/2014/04/17/unleash-your-ajax-requests-with-cors/

+0

bedeutet es, ich sollte meine JS Post ändern und erstellen. eine "Optionen" Anfrage? – benams

+1

Ich habe Proben hinzugefügt. Grundsätzlich Preflight wird von Browser unter der Haube durchgeführt. – kwarunek

+0

Yeah, ich fand es nach diesem Kommentar. Vielen Dank, es war wirklich hilfreich! – benams

4

Die Antwort von kwarunek führte mich in die Lösung für meine Probleme mit der PUT und DELETE Anfrage. Das einzige Problem ist, dass die Lösung für das Beispiel mit GET und POST über-geeignet ist. In diesem Fall genügt die Zeile

self.set_header("Access-Control-Allow-Origin", "*") 

eigentlich (wenn der Browser CORS nicht vor allen anderen blockiert) Dies ist jedoch am wichtigsten für die PUT- und DELETE-Anfragen. Was hier auf der Netzwerkebene passiert, kann etwas komplexer sein als im GET/POST-Fall.

"Wenn die Anfrage eine" nicht einfache "Anfrage ist, sendet der Browser zuerst eine datenlose" Preflight "OPTIONS-Anfrage, um zu verifizieren, dass der Server die Anfrage akzeptiert. Eine Anfrage ist nicht einfach bei Verwendung einer HTTP-Verb anders als GET oder POST (zB PUT, DELETE)."cf. non-simple requests

class BaseHandler(tornado.web.RequestHandler): 

    def set_default_headers(self): 
     print("setting headers!!!") 
     self.set_header("Access-Control-Allow-Origin", "*") 
     self.set_header("Access-Control-Allow-Headers", "x-requested-with") 
     self.set_header('Access-Control-Allow-Methods', ' PUT, DELETE, OPTIONS') 

    def options(self): 
     # no body 
     self.set_status(204) 
     self.finish() 

Nun werden alle Handler, die von BaseHandler erben sind voll CORS-fähig:

class MyHandler(BaseHandler): 

    def put(self): 
     self.write('some post') 

    def delete(self): 
     self.write('some get')