web-dev-qa-db-ja.com

トルネードサーバー:CORSリクエストを有効にする

私はクラスを持つ単純な竜巻サーバーを持っています:

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

通常の(CORSなしの)要求が行われると、サーバーはAccess-Control-Allow-Originヘッダーを含め、期待どおりに応答します。しかし、(jQuery.postを使用して)別のドメインからの投稿リクエストを行うと、応答は404になり、エラーが表示されます:「XMLHttpRequest cannot load http:// dev-machine:8090/handshake 。要求されたリソースに 'Access-Control-Allow-Origin'ヘッダーがありません。したがって、オリジン ' http:// localhost:809 'はアクセスを許可されていません。応答にはHTTPステータスコードがありました404」

私が何かを逃したかどうかわかりますか? (別のヘッダー/その他の構成/その他)

11
benams

コードにプリフライト、OPTIONSリクエストがありません。

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

Cross-Origin Resource Sharing標準は、サーバーがWebブラウザーを使用してその情報を読み取ることが許可されているオリジンのセットを記述できるようにする新しいHTTPヘッダーを追加することで機能します。さらに、ユーザーデータに副作用を引き起こす可能性があるHTTPリクエストメソッド(特に、GET以外のHTTPメソッド、またはPOST特定のMIMEタイプでの使用)の場合、仕様ではブラウザにHTTP OPTIONSリクエストメソッドを使用してサーバーからサポートされているメソッドを要求し、サーバーから「承認」されると、実際のリクエストを実際のHTTPリクエストメソッドで送信します。サーバーは、クライアントに「資格情報」を通知することもできます。 (CookieとHTTP認証データを含む)はリクエストとともに送信する必要があります。

プリフライトハンドラーを実装するには、同じヘッダーで本文なしのオプションハンドラーを追加するだけです。

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

私は追加しました x-requested-with許可リストのヘッダー。そして、ここに簡単な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");
   }
 });

そして、corsに関するいくつかの本当に良い記事- http://dev.housetrip.com/2014/04/17/unleash-your-ajax-requests-with-cors/

36
kwarunek

Kwarunekの回答により、PUTとDELETE要求に関する問題の解決策が見つかりました。唯一のことは、GETとPOSTの例ではソリューションが適切すぎることです。この場合、行

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

実際には十分です(ブラウザーがCORSをブロックしない場合)。ただし、PUTおよびDELETE要求に最も関連があります。ここでネットワークレベルで発生することは、GET/POSTの場合よりも少し複雑になる可能性があります。

「リクエストが「単純ではない」リクエストの場合、ブラウザは最初にデータのない「プリフライト」OPTIONSリクエストを送信して、サーバーがリクエストを受け入れることを確認します。HTTP以外の動詞を使用する場合、リクエストは単純ではありませんGETまたはPOST(eg 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()

これで、BaseHandlerを継承するすべてのハンドラーが完全にCORS対応になります。

class MyHandler(BaseHandler):

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

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

以前の回答でも、次のCORSエラーが発生しました。

Cross-Origin Request Blocked:Same Origin Policyは http://127.0.0.1:9999/home?message=Input%20to%20API ..でリモートリソースの読み取りを許可しません(理由:トークンがありません ' CORSプリフライトチャネルのCORSヘッダー「Access-Control-Allow-Headers」のaccess-control-allow-Origin)。

solutionは、ヘッダーも許可することです。

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', 'GET, PUT, DELETE, OPTIONS')
        # HEADERS!
        self.set_header("Access-Control-Allow-Headers", "access-control-allow-Origin,authorization,content-type") 

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

これでうまくいきました。

def set_default_headers(self):
    self.set_header("Content-Type", "application/json")
    self.set_header("Access-Control-Allow-Origin", "*")
    self.set_header("Access-Control-Allow-Headers", "content-type")
    self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PATCH, PUT')
1
Binh Ho