web-dev-qa-db-ja.com

GETリクエストではなくOPTIONSリクエストを受けるのはなぜですか?

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js" type="text/javascript"></script>
<script>
$.get("http://example.com/", function(data) {
     alert(data);
});
</script>

それはそのURLにOPTIONSリクエストを行い、その後コールバックは何も呼び出されません。

クロスドメインでない場合は、うまく機能します。

JQueryは<script>ノードで呼び出しを行い、ロードされたときにコールバックを行うべきではありませんか私は結果を得ることができないことを理解しています(それがクロスドメインであるので)、しかしそれはOKです。電話をかけたいだけです。これはバグですか、それとも私は何か悪いことをしていますか?

260
Paul Tarjan
88
Paul Tarjan

によると MDN

プリフライトリクエスト

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

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

あなたが投稿しようとしている場合

必ずフォームデータをJSON.stringifyしてtext/plainとして送信してください。

<form id="my-form" onSubmit="return postMyFormData();">
    <input type="text" name="name" placeholder="Your Name" required>
    <input type="email" name="email" placeholder="Your Email" required>
    <input type="submit" value="Submit My Form">
</form>

function postMyFormData() {

    var formData = $('#my-form').serializeArray();
    formData = formData.reduce(function(obj, item) {
        obj[item.name] = item.value;
        return obj;
    }, {});
    formData = JSON.stringify(formData);

    $.ajax({
        type: "POST",
        url: "https://website.com/path",
        data: formData,
        success: function() { ... },
        dataType: "text",
        contentType : "text/plain"
    });
}
5
Derek Soike

そのようなURLが与えられたときにjQueryが自然にJSONPリクエストを行うとは思わない。ただし、コールバックに使用する引数を指定するとJSONPリクエストが行われます。

$.get("http://metaward.com/import/http://metaward.com/u/ptarjan?jsoncallback=?", function(data) {
     alert(data);
});

その引数( "jsoncallback"と呼ばれる必要はない)を利用するのは完全に受信側のスクリプト次第であるので、この場合関数は決して呼び出されないでしょう。しかし、metaward.comのスクリプトを実行したいだけであると述べたので、それが可能になります。

2
VoteyDisciple

私は同じ問題を抱えていました。私の修正は私のPHPスクリプトにヘッダを追加することでした。これは開発環境にある時だけ存在します。

これにより、クロスドメインリクエストが可能になります。

header("Access-Control-Allow-Origin: *");

これは、プリフライト要求に、クライアントが必要なヘッダーを送信しても問題ないことを通知します。

header("Access-Control-Allow-Headers: *");

この方法では、リクエストを修正する必要はありません。

潜在的に漏洩する可能性があるあなたの開発データベースに機密データがあるなら、あなたはこれについて二度考えるかもしれません。

1
fivebit

「application/json」を「text/plain」に変更し、JSON.stringify(request)を忘れないでください。

var request = {Company: sapws.dbName, UserName: username, Password: userpass};
    console.log(request);
    $.ajax({
        type: "POST",
        url: this.wsUrl + "/Login",
        contentType: "text/plain",
        data: JSON.stringify(request),

        crossDomain: true,
    });
1
David Lopes

実際、セキュリティ上の理由から、クロスドメインのAJAX(XMLHttp)要求は許可されません(クライアント側から "制限付き" Webページを取得してサーバーに返送することを検討してください)。セキュリティの問題)。

唯一の回避策はコールバックです。これは、新しいスクリプトオブジェクトを作成し、JSON値(myFunction({data}))を持つコールバックであるエンドサイドJavaScriptを指すsrcを指すことです。myFunctionは、データを使って何かをする関数です(たとえば、それを格納します)。変数に)。

1
Adrián Navarro

私の場合、同じWebサーバーにjQuery POSTを発行していたので、この問題はCORSとは無関係です。データはJSONでしたが、dataType: 'json'パラメーターを省略しました。

上記のDavid Lopesの回答に示されているように、私はcontentTypeパラメータを持っていませんでした(追加もしませんでした)。

0
GarDavis

ヘッダーをフォローすることで修正できました

Access-Control-Allow-Origin
Access-Control-Allow-Headers
Access-Control-Allow-Credentials
Access-Control-Allow-Methods

Nodejsを使用している場合、ここにコピー/貼り付けできるコードがあります。

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin','*');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH');
  next();
});
0
obai

FirefoxとOpera(Macでもテスト済み)のように見えますが、これがクロスドメインであることは好きではありません(ただしSafariは問題ありません)。

リモートページを丸めるには、ローカルサーバー側のコードを呼び出す必要があります。

0
helloandre