web-dev-qa-db-ja.com

OPTIONSリクエストが送信されるのはなぜですか?それを無効にできますか?

私はWeb APIを構築しています。 POSTにChromeを使用し、APIにGETを実行するたびに、実際のリクエストの前にOPTIONSリクエストが送信されることがあり、これは非常に面倒です。現在私はサーバーにOPTIONSリクエストを無視させます。今私の質問は、サーバーの負荷を倍増するためにOPTIONSリクエストを送信するのが良いことですか?ブラウザがOPTIONSリクエストを送信しないようにする方法はありますか?

308
Elgs Qian Chen

編集2018-09-13 :このフライト前のリクエストと、このレスポンスの最後にそれを回避する方法についてのいくつかの精度を追加しました。

OPTIONSリクエストはCross-Origin resource sharing (CORS)pre-flightリクエストと呼んでいます。

あなたが特定の状況で異なる起源にまたがって要求をするとき、それらは必要です。

この飛行前の要求は、行われている要求がサーバーによって信頼されていることを確認するための安全対策として、一部のブラウザーによって行われます。サーバが、リクエストで送信されたメソッド、Origin、およびヘッダが安全に動作していることを理解していることを意味します。

クロスオリジンリクエストを実行しようとしているときはいつでも、サーバはこれらのリクエストを無視せずに処理する必要があります。

良いリソースはここにあります http://enable-cors.org/ /

快適にするためにこれらを処理する方法は、OPTIONSメソッドを持つすべてのパスに対して、サーバーがこのヘッダーを含む応答を送信するようにすることです。

Access-Control-Allow-Origin: *

これはブラウザにサーバがどんなOriginからの要求にも答えても構わないと思っていることを伝えます。

サーバーにCORSサポートを追加する方法の詳細については、以下のフローチャートを参照してください。

http://www.html5rocks.com/static/images/cors_server_flowchart.png

CORS Flowchart


編集2018-09-13

MDNドキュメント :で説明されているように、CORSのOPTIONSリクエストはいくつかのケースでのみ引き起こされます。

一部の要求では、CORSのプリフライトは発生しません。この記事ではこれらを「単純要求」と呼びますが、Fetch仕様(CORSを定義する)ではこの用語は使用されていません。 CORSプリフライトをトリガーしない要求(いわゆる「単純要求」)は、以下のすべての条件を満たすものです。

許可されているメソッドは次のとおりです。

  • GET
  • HEAD
  • POST

ユーザエージェントによって自動的に設定されるヘッダ(例えば、Connection、User-Agent、またはFetch仕様で「禁止されたヘッダ名」として定義された名前を持つ他のヘッダなど)を除いて、許可される唯一のヘッダ手動で設定されるのは、Fetch仕様で「CORSセーフリストの要求ヘッダー」として定義されているものです。

  • 受け入れる
  • 受け入れ言語
  • コンテンツ言語
  • コンテンツタイプ(ただし、以下の追加要件に注意してください)
  • 北朝鮮
  • ダウンリンク
  • データ保存
  • ビューポート幅

Content-Typeヘッダーに許可されている唯一の値は次のとおりです。

  • application/x-www-form-urlencoded
  • マルチパート/フォームデータ
  • テキスト/プレーン

リクエストで使用されるXMLHttpRequestUploadオブジェクトには、イベントリスナーは登録されていません。これらはXMLHttpRequest.uploadプロパティを使ってアクセスされます。

リクエストでReadableStreamオブジェクトは使用されません。

283
Leo Correa

この問題を見てきましたが、以下に、この問題に対する私の結論と解決策を示します。

CORS戦略によれば (強く読むことを強くお勧めします)必要であればブラウザにOPTIONSリクエストの送信を強制的に停止させることはできません。

これを回避する方法は2つあります。

  1. あなたの要求が「単純な要求」であることを確認してください
  2. OPTIONSリクエストにAccess-Control-Max-Ageを設定します

簡単な依頼

単純なクロスサイトリクエストは、以下のすべての条件を満たすものです。

許可されているメソッドは次のとおりです。

  • GET
  • HEAD
  • POST

ユーザエージェントによって自動的に設定されるヘッダ(例えば、接続、ユーザエージェントなど)とは別に、手動で設定することが許される唯一のヘッダは以下の通りである。

  • 受け入れる
  • 受け入れ言語
  • コンテンツ言語
  • コンテンツタイプ

Content-Typeヘッダーに許可されている唯一の値は次のとおりです。

  • application/x-www-form-urlencoded
  • マルチパート/フォームデータ
  • テキスト/プレーン

単純なリクエストではフライト前のOPTIONSリクエストは発生しません。

OPTIONSチェック用のキャッシュを設定します

OPTIONSリクエストにAccess-Control-Max-Ageを設定して、期限が切れるまでアクセス権を確認しないようにすることができます。

Access-Control-Max-Ageは、別のプリフライト要求を送信せずにプリフライト要求への応答をキャッシュできる期間を秒単位で指定します。

注目される制限

  • Chromeの場合、Access-Control-Max-Ageの最大秒数は600で、10分です。 chrome source code
  • Access-Control-Max-Ageは毎回1つのリソースに対してのみ機能します。例えば、同じURLパスを持つGETリクエストは異なるクエリは異なるリソースとして扱われます。そのため、2番目のリソースへのリクエストはまだプリフライトリクエストをトリガーします。
159
Neekey

プレフライトされたOPTIONSリクエストの実際の必要性については、この回答を参照してください。 CORS - プリフライトリクエストを導入する動機は何ですか?

OPTIONSリクエストを無効にするには、ajaxリクエストに対して以下の条件を満たす必要があります。

  1. リクエストが 'application/xml'や 'application/json'などのカスタムHTTPヘッダを設定しない
  2. リクエストメソッドは、GET、HEAD、またはPOSTのいずれかでなければなりません。 POSTの場合、コンテンツタイプはapplication/x-www-form-urlencodedmultipart/form-data、またはtext/plainのいずれかになります。

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

135
device_exec

デバッグコンソールを開いてDisable Cacheオプションをオンにすると、プリフライトリクエストは常に送信されます(つまり、各リクエストの前に)。キャッシュを無効にしないと、フライト前のリクエストは(サーバーごとに)1回だけ送信されます。

41
Nir

はい、それはオプションの要求を回避することが可能です。オプションリクエストは、データを別のドメインに送信(投稿)するときのプリフライトリクエストです。ブラウザのセキュリティ問題です。しかし、我々は別の技術を使うことができます:iframeトランスポート層。 CORSの設定を忘れて既製のソリューションを使用することを強くお勧めします。

ここで見てみましょう: https://github.com/jpillora/xdomain

そして実用的な例: http://jpillora.com/xdomain/

38
user889349

以前の記事ですでに述べたように、OPTIONSリクエストは理由があります。サーバーからの応答時間が長い場合(海外接続など)に問題がある場合は、ブラウザーにプリフライトリクエストをキャッシュさせることもできます。

サーバーにAccess-Control-Max-Ageヘッダーを付けて応答させ、同じエンドポイントに送信される要求に対してはプリフライト要求がキャッシュされ、もう発生しないようにします。

14
enpenax

それが存在する理由を理解しているが認証なしでOPTIONS呼び出しを処理しないAPIにアクセスする必要がある開発者のために、私は一時的な答えを必要と稼働中です。

SafariではCORSを、MacではChromeを無効にできることがわかりました。

Chromeで同じOriginポリシーを無効にする

Chrome:Chromeを終了し、端末を開いて次のコマンドを貼り付けます:open /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir

Safari: Safariで同一オリジンポリシーを無効にする

あなたがSafariのsame-originポリシー(私は9.1.1を持っています)を無効にしたいのなら、あなたは開発者メニューを有効にする必要があるだけです。

12
Joseph Juhnke

私はこの問題を次のように解決しました。

if($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && ENV == 'devel') {
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Headers: X-Requested-With');
    header("HTTP/1.1 200 OK");
    die();
}

開発専用です。これで私は9msと500msではなく8sと500msを待っています。本番用のJSアプリは本番用のマシンと同じマシン上にあるので、OPTIONSはありませんが、開発は私のローカルです。

6
AntiCZ

できませんがJSONPを使用したCORSを避ける​​ことができます。

5
Jose Mato

一日半費やして同様の問題を解決しようとしたところ、 _ iis _ と関係があることがわかりました。

私のWeb APIプロジェクトは次のように設定されています。

// WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
    var cors = new EnableCorsAttribute("*", "*", "*");
    config.EnableCors(cors);
    //...
}

CORS固有の設定オプションがありませんでした web.config> system.webServerノードで、多数の投稿で見たことがあります

global.asaxまたはデコレータとしてのコントローラにCORS固有のコードがない

問題は アプリプールの設定 です。

マネージドパイプラインモード はクラシック( 統合 )に設定され、 Identity はネットワークサービス( ApplicationPoolIdentity に変更)に設定されました。

これらの設定を変更して(そしてアプリプールを更新して)それを修正しました。

0
Ju66ernaut