web-dev-qa-db-ja.com

XMLHttpRequestの変更POST OPTIONに

私はこのコードを持っています:

net.requestXHR = function() {
    this.xhr = null;
    if(window.XMLHttpRequest === undefined) {
        window.XMLHttpRequest = function() {
            try {
                // Use the latest version of the activex object if available
                this.xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0");
            }
            catch(e1) {
                try {
                    // Otherwise fall back on an older version
                    this.xhr = new ActiveXObject("Mxsml2.XMLHTTP.3.0");
                }
                catch(e2) {
                    //Otherwise, throw an error
                    this.xhr = new Error("Ajax not supported in your browser");
                }
            }
        };
    }
    else
        this.xhr = new XMLHttpRequest();
}
net.requestXHR.prototype.post = function(url, data) {
    if(this.xhr != null) {
        this.xhr.open("POST", url);
        this.xhr.setRequestHeader("Content-Type", "application/json");
        this.xhr.send(data);
    }
}

    var rs = new net.requestSpeech();
    console.log(JSON.stringify(interaction));
    rs.post("http://localhost:8111", JSON.stringify(interaction));

送信が実行されると、このログがあります:

OPTIONS http://localhost:8111/ [HTTP/1.1 405 Method Not Allowed 74ms]

そして、localhost:8111には、投稿を受け入れるreslet serverResourceがありますが、同じOriginポリシーの問題ですか? allow-Originヘッダーを配置するようにrestletを変更し、別のGET http要求(jquery内)でテストし、正常に動作します。私はhtml5ブラウザを使用しており、サーバーが応答にヘッダーを配置しているため、同じOriginが解決する問題があります。 OPTIONをPOSTに変更する理由?ありがとう!

重複する可能性はありますか?:いいえ、しかしそれは本当です、問題は両方の質問で同じですが、ブラウザに問題があるという質問と、他の質問が最初にjqueryを指しているので、私の質問は参照です。経験上、重複する時間はカウントされません。答えは異なりますが、両方の質問が互いに補完し合うことは事実です。

48
Kalamarico

はい、これは「同一起源の問題」です。別のサーバーまたは別のポートにリクエストを送信しています。つまり、クロスサイトHTTPリクエストです。そのようなリクエストについて ドキュメント が言わなければならないことは次のとおりです。

さらに、サーバーのデータに副作用を引き起こす可能性のあるHTTP要求メソッド(特に、GET以外のHTTPメソッド、または特定のMIMEタイプでのPOSTの使用)の場合、仕様ではブラウザはリクエストを「プリフライト」し、HTTP OPTIONSリクエストメソッドでサーバーからサポートされているメソッドを要求し、サーバーから「承認」されると、実際のHTTPリクエストメソッドで実際のリクエストを送信します。

CORS標準 (「プリフライトを使用したクロスオリジンリクエスト」セクション)に詳細な説明があります。サーバーは、OPTIONSリクエストを許可し、リクエストを許可するAccess-Control-Allow-OriginAccess-Control-Allow-Headers、およびAccess-Control-Allow-Methodsヘッダーで応答を送信する必要があります。その後、ブラウザは実際のPOSTリクエストを作成します。

70
Wladimir Palant

私はajaxコンテンツを送信したJavaScriptコードからこの正確な問題を抱えていました。

プリフライトでのクロスオリジンリクエストを許可するには、請願書を受け取っていた.ASPXでこれを行う必要がありました。

//Check the petition Method
if (Request.HttpMethod == "OPTIONS")
{
    //In case of an OPTIONS, we allow the access to the Origin of the petition
    string vlsOrigin = Request.Headers["Origin"];
    Response.AddHeader("Access-Control-Allow-Origin", vlsOrigin);
    Response.AddHeader("Access-Control-Allow-Methods", "POST");
    Response.AddHeader("Access-Control-Allow-Headers", "accept, content-type");
    Response.AddHeader("Access-Control-Max-Age", "1728000");
}

請願書でどのヘッダーが要求されているかを注意深く確認する必要があります。 Fiddlerを使用してそれらをチェックしました。

これが将来誰かに役立つことを願っています。

9

他の人が指摘したように、これはCORSの問題です。

これは、NGINXでの処理方法です( this source に基づいています):

location / {
    if ($request_method = OPTIONS ) {
        add_header Access-Control-Allow-Origin "http://example.com";
        add_header Access-Control-Allow-Methods "GET, OPTIONS";
        add_header Access-Control-Allow-Headers "Authorization";
        add_header Access-Control-Allow-Credentials "true";
        add_header Content-Length 0;
        add_header Content-Type text/plain;
        return 200;
    }
}

任意のオリジンからのCORSリクエストを許可する場合は、置き換え、

add_header Access-Control-Allow-Origin "http://example.com";

add_header Access-Control-Allow-Origin "*";

認証を使用しない場合、このビットは必要ありません。

add_header Access-Control-Allow-Headers "Authorization";
add_header Access-Control-Allow-Credentials "true";

開発中のAPIの場合、3つのリクエストメソッドをホワイトリストに登録する必要がありました:GET、POST and OPTIONS、およびX-App-Idヘッダーなので、これが私がやったことです。

if ($request_method = OPTIONS ) {
    add_header Access-Control-Allow-Origin "*";
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
    add_header Access-Control-Allow-Headers "X-App-Id";
    add_header Content-Length 0;
    add_header Content-Type text/plain;
    return 200;
}
2
Nino Škopac