GET / POST / PUT / DELETEの代わりにOPTIONSを送信するChromeのAJAX?


107

私は職場で内部Webアプリケーションに取り組んでいます。IE10ではリクエストは正常に機能しますが、Chromeでは、すべてのAJAXリクエスト(多数あります)は、指定したメソッドではなく、OPTIONSを使用して送信されます。技術的には、私の要求は「クロスドメイン」です。このサイトはlocalhost:6120で提供されており、AJAXリクエストを送信するサービスは57124にあります。このクローズされたjqueryバグは問題を定義していますが、実際の修正ではありません。

ajaxリクエストで適切なhttpメソッドを使用するにはどうすればよいですか?

編集:

これは、すべてのページのドキュメントロードにあります。

jQuery.support.cors = true;

そして、すべてのAJAXは同様に構築されています。

var url = 'http://localhost:57124/My/Rest/Call';
$.ajax({
    url: url,
    dataType: "json",
    data: json,
    async: true,
    cache: false,
    timeout: 30000,
    headers: { "x-li-format": "json", "X-UserName": userName },
    success: function (data) {
        // my success stuff
    },
    error: function (request, status, error) {
        // my error stuff
    },
    type: "POST"
});

2
そのバグレポートの最後のコメントはそれをかなりよく説明しています...
Kevin B

1
私がやっていることはすべてバニラ(そして私のコードはjqueryバグのコードに似ている)だったので、それは私の心を揺さぶった。それはさておき、それを含めないことの言い訳にはなりません。BRB、いくつかのサンプルコードを取得。
Corey Ogburn 2014

3
IEは、要求がクロスオリジンであるかどうかを判断するときにポート番号を考慮しないことに注意してください。
レイニコラス2014

@KevinB:私たちのRESTサービスは、httpメソッドに基づいてさまざまなことを行うので、さまざまなリクエストを利用します。すべてをGETに切り替えることは、有効な修正ではありません。また、Dark Falconの回答によれば、X-UserNameとその他のカスタムヘッダーがリクエストに含まれているため、とにかく役に立ちません。
Corey Ogburn 2014

クロスオリジンリクエストを作成する場合、クロスオリジンリクエストが適切に機能するためには、クロスオリジンリクエストに適用されるすべてのルールに従う必要があるという事実は変わりません。クロスオリジンリクエストには通常、OPTIONSリクエストが含まれます。適切に処理すれば問題は解消します。これを(APIを変更せずに)解決する他の唯一の方法は、サーバー側のコードを使用してAPIと対話するプライマリページと同じサーバー上にスクリプトを置くことです。
ケビンB

回答:


136

ChromeはCORSヘッダーを探すリクエストをプリフライトしています。リクエストが受け入れ可能であれば、実際のリクエストを送信します。このクロスドメインを実行している場合は、それに対処するか、リクエストを非クロスドメインにする方法を見つける必要があります。これが、jQueryのバグが修正されずにクローズされた理由です。これは仕様によるものです。

単純な要求(前述)とは異なり、「プリフライト」要求は、実際の要求が安全に送信できるかどうかを判断するために、最初にOPTIONSメソッドによってHTTP要求を他のドメインのリソースに送信します。クロスサイトリクエストは、ユーザーデータに影響を与える可能性があるため、このようにプリフライトされます。特に、リクエストは次の場合にプリフライトされます。

  • GET、HEAD、POST以外のメソッドを使用します。また、POSTを使用して、application / x-www-form-urlencoded、multipart / form-data、text / plain以外のContent-Typeでリクエストデータを送信する場合、たとえば、POSTリクエストがXMLペイロードをサーバーに送信する場合application / xmlまたはtext / xmlを使用すると、リクエストはプリフライトされます。
  • リクエストにカスタムヘッダーを設定します(たとえば、リクエストはX-PINGOTHERなどのヘッダーを使用します)

20
カスタムヘッダー。それがおそらくプリフライトOPTIONS呼び出しを開始するものです。
コーリーオグバーン

18

リクエストという事実に基づいて がデフォルトのポート80/443で送信されないこのAjax呼び出しは自動的にクロスオリジンリソース(CORS)リクエストと見なされます。つまり、リクエストは、以下をチェックするOPTIONSリクエストを自動的に発行します。サーバー側/サーブレット側のCORSヘッダー。

これは設定しても発生します

crossOrigin: false;

または省略した場合でも。

その理由は単にそれだけですlocalhost != localhost:57124localhostポートなしでのみに送信してみてください-要求されたターゲットに到達できないため失敗しますが、ドメイン名が等しい場合、POSTの前にOPTIONS要求なしで要求が送信されることに注意してください。


3

私はケビンBに同意します、バグレポートはそれをすべて言います。クロスドメインのajax呼び出しを実行しようとしているようです。同じオリジンポリシーに詳しくない場合は、https//developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScriptから開始できます

これがクロスドメインのajax呼び出しを意図していない場合は、ターゲットURLを相対化して、問題が解消するかどうかを確認してください。あなたが本当にJSONPを必死に見ているなら、注意してください、騒乱が潜んでいます。本当に私たちがあなたを助けるためにできることはこれ以上ありません。


1
私たちのシステム構造は私が変更できないものです。別のポートを使用することは、私たちのアーキテクチャの要件です。元のポリシーは同じですが、実装したCORSで十分だと思いました。どうやらそうではない。
Corey Ogburn

2
サーバーがJSON応答を返す場合は、JSONPメソッドを調べて、責任を持って使用することができます。
jgitter

1
私はあなたと議論することは本当に気にしませんが、JSONPはスクリプトタグを使用して別のドメインからデータを取得し、その結果をコールバック関数に送信します。結果がjsonでない場合は、はるかに困難になります。
jgitter 2014

1
いいえ、それほど難しくありません。実際、どのような場合でも、応答は有効なJSONであってはなりません。代わりに、サーバーは次のようなものを返しますcallbackfunc(somedata)。ご覧のとおり、これは有効なJSONではありません。また、somedata文字列、数値、または任意の文字にすることができます。
レイニコラス2014

1
私はPostmanを使用しており、リクエストメソッドが正しく送信されます(例:「PUT」、「DELETE」など)。しかし、私がコードからそれを行おうとすると、常にリクエストメソッドOPTIONSでそれらを送信します。Postmanがそれをどのように行うことができるか私にはわかりません。
ErwinGO、2015

1

可能であれば、通常のGET / POSTを介して別の名前でparamsを渡し、サーバー側のコードで処理できるようにします。

CORSをバイパスするために自分のプロキシで同様の問題があり、ChromeでPOST-> OPTIONの同じエラーが発生しました。それはAuthorization私の場合("x-li-format"そして"X-UserName"ここではあなたの場合)のヘッダーでした。最終的にはダミーの形式(AuthorizatinJackGETなど)で渡してしまい、宛先への呼び出しを行うときにプロキシのコードを変更してヘッダーに変換しました。ここではPHPです:

if (isset($_GET['AuthorizationJack'])) {
    $request_headers[] = "Authorization: Basic ".$_GET['AuthorizationJack'];
}

1

私の場合、AWS(API Gateway)でホストされているAPIを呼び出しています。API自身のドメイン以外のドメインからAPIを呼び出そうとしたときにエラーが発生しました。私はAPIの所有者なので、Amazonのドキュメントで説明されているように、テスト環境でCORSを有効にしました

本番環境では、リクエストとAPIが同じドメインにあるため、このエラーは発生しません。

お役に立てば幸いです。


0

答え @Darkファルコンによって、私は単にそれに対処します

私の場合、node.jsサーバーを使用していて、セッションが存在しない場合は作成します。OPTIONSメソッドにはセッションの詳細が含まれていないため、POSTメソッドのリクエストごとに新しいセッションが作成されます。

そのため、create-session-if-not-existのアプリルーチンで、メソッドがOPTIONSであるかどうかを確認するチェックを追加しました。そうである場合は、セッション作成の部分をスキップします。

    app.use(function(req, res, next) {
        if (req.method !== "OPTIONS") {
            if (req.session && req.session.id) {
                 // Session exists
                 next();
            }else{
                 // Create session
                 next();
          }
        } else {
           // If request method is OPTIONS, just skip this part and move to the next method.
           next(); 
        }
    }

0

「プリフライト」リクエストは、実際のリクエストが安全に送信できるかどうかを判断するために、最初にOPTIONSメソッドによるHTTPリクエストを他のドメインのリソースに送信します。クロスサイトリクエスト

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


1
もう少し情報を追加できますか?あなたの答えはコメントのようです。:)
バダカダブラ2017年

0

axiosの使用を検討してください

axios.get( url,
{ headers: {"Content-Type": "application/json"} } ).then( res => {

  if(res.data.error) {

  } else { 
    doAnything( res.data )
  }

}).catch(function (error) {
   doAnythingError(error)
});

私はフェッチとaxios を使用してこの問題を完全に解決しました。


5
Axiosも最初のオプションを使用します
Skylin R

0

非常によく似た問題が発生しました。Firefoxですべてが正しく機能し、Chromeで失敗する理由を理解するために、ほぼ半日かかりました。私の場合は、リクエストヘッダーのフィールドが重複している(またはタイプが間違っている)ためです。


0

XHRの代わりにフェッチを使用すると、クロスドメインであってもリクエストはプリライトされません。


-1
 $.ajax({
            url: '###',
            contentType: 'text/plain; charset=utf-8',
            async: false,
            xhrFields: {
                withCredentials: true,
                crossDomain: true,
                Authorization: "Bearer ...."
            },

            method: 'POST',

            data: JSON.stringify( request ),
            success: function (data) {
                console.log(data);
            }
        });

contentType: 'text / plain; charset = utf-8 '、または単にcontentType:' text / plain 'が機能します!よろしく!!


これは質問と何の関係がありますか?
Corey Ogburn

こんにちは、これでタイトルの問題が解決すると思います。このコンテンツタイプでは、OPTIONSメソッドを渡します。よろしくお願いします
David Lopes

ContentTypeはメソッドとは何の関係もありません。
Corey Ogburn

あなたの言っていることがわかりますが、やってみてください。ブラウザによっては、コンテンツタイプがリクエストに影響を与え、メソッドを変更する場合があります。
David Lopes
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.