2016-02-07 12 views
5

Mam prosty serwer tornado, który ma klasę:serwer Tornado: enable CORS żąda

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

Przy regularnym (bez CORS) wniosek został złożony, odpowiedzi serwera, jak oczekiwano, w tym dostępu Sterowanie Nagłówek Allow-Origin. Ale kiedy wysyłam żądanie postu pochodzące z innej domeny (przy użyciu jQuery.post), odpowiedź jest równa 404 i wyświetlany jest błąd: "XMLHttpRequest nie może załadować http://dev-machine:8090/handshake. W żądanym zasobie nie ma nagłówka" Access-Control-Allow-Origin ". Początek "http://localhost:8090" jest zatem niedozwolony, odpowiedź miała kod stanu HTTP 404. "

Czy możesz powiedzieć, że czegoś mi brakuje? (inny nagłówek/inna konfiguracja/cokolwiek innego)

+0

że' pass' jest zbędny/źle –

Odpowiedz

21

Twój kod nie zawiera preflight, prośba OPTIONS.

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

The Cross-Origin Resource Sharing standardowe prace dodając nowe nagłówki HTTP serwery, które pozwalają opisać zbiór pochodzeniu, które są dopuszczone do odczytać te informacje za pomocą przeglądarki internetowej. Ponadto, dla metod żądań HTTP, które mogą powodować skutki uboczne dla danych użytkownika (w szczególności w przypadku , w przypadku metod HTTP innych niż GET lub w przypadku użycia POST z niektórych typów MIME), specyfikacja wymaga, aby przeglądarki "sprawdzały wstępnie" żądanie. , pozyskiwanie obsługiwanych metod z serwera za pomocą metody żądania HTTP OPTIONS, a następnie po "zatwierdzeniu" od serwera, wysyłając rzeczywiste żądanie za pomocą rzeczywistego żądania HTTP . Serwery mogą również powiadamiać klientów, czy "poświadczenia" (w tym dane cookie i dane uwierzytelniania HTTP) powinny być wysyłane z żądaniami .

Aby zaimplementować podgląd wstępny, wystarczy dodać opcje obsługi z tymi samymi nagłówkami i bez korpusu.

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() 

edit

Dodałem x-requested-with nagłówek do listy dozwolony. A oto prosty przykład jQuery:

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

i niektóre naprawdę dobry artykuł o Cors - http://dev.housetrip.com/2014/04/17/unleash-your-ajax-requests-with-cors/

+0

to znaczy muszę zmienić mój JS słupek i tworzyć. Określenie „Opcje” żądanie? – benams

+1

Dodałem próbek. Zasadniczo inspekcji wstępnej odbywa się przez przeglądarkę pod maską. – kwarunek

+0

Tak, uważam, że to po pisał ten komentarz. Dziękuję, to było bardzo pomocne! – benams

4

Odpowiedź przez kwarunek doprowadziło mnie do sporządzania roztworu do mojego kłopoty z PUT i wniosek usunąć. Jedyną rzeczą jest to, że rozwiązanie jest zbyt nieodpowiednie dla przykładu z GET i POST. W takim przypadku linia wystarczająca (jeśli przeglądarka nie blokuje CORS przed wszystkim) jest w rzeczywistości wystarczająca. Jest to jednak najbardziej istotne dla żądań PUT i DELETE. To, co dzieje się tutaj na poziomie sieci, może być nieco bardziej złożone niż w przypadku GET/POST.

"Jeśli żądanie jest" nie-proste ", przeglądarka wysyła najpierw bez danych żądanie inspekcji OPTLINE, aby sprawdzić, czy serwer zaakceptuje żądanie. Żądanie nie jest proste przy korzystaniu z Czasownik HTTP inny niż GET lub POST (np. 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() 

Teraz wszystkie koparki, które dziedziczą z BaseHandler są w pełni zdolne CORS-:

class MyHandler(BaseHandler): 

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

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