XMLHttpRequest изменяет POST на OPTION - PullRequest
48 голосов
/ 16 ноября 2011

у меня есть этот код:

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, который принимает почту, это проблема той же политики происхождения? Я изменил рестлет, чтобы поместить заголовок allow-origin, и я проверил его с помощью другого запроса GET http (в jquery), и все в порядке. У меня проблема с тем же разрешением источника, потому что я использую браузер html5, а мой сервер помещает заголовки в ответ, так почему отправка показывает мне эту ошибку? зачем менять POST на OPTION? Спасибо!

Возможно, дубликат? Я думаю, что нет, но это правда, проблема в том, то же самое для обоих вопросов, но мой относится, так как вопрос, который есть проблема с браузером, а другой, первый указывает на JQuery. По опыту время не считается дубликатом, ответы разные, но это правда, что оба вопроса дополняют друг друга.

Ответы [ 3 ]

70 голосов
/ 16 ноября 2011

Да, это «проблема с политикой того же происхождения».Вы делаете запрос либо на другой сервер, либо на другой порт, то есть это межсайтовый HTTP-запрос.Вот что документация говорит о таких запросах:

Кроме того, для методов HTTP-запросов, которые могут вызывать побочные эффекты на данных сервера (в частности, для HTTP-методов, другихчем GET, или для POST использования с определенными типами MIME), спецификация требует, чтобы браузеры "предварительно отправляли" запрос, запрашивая поддерживаемые методы с сервера с помощью метода запроса HTTP OPTIONS, а затем, после "утверждения"с сервера, отправив фактический запрос методом фактического HTTP-запроса.

Более подробное описание содержится в стандарте CORS (раздел «Перекрестный запрос с предпечатной проверкой»)).Ваш сервер должен разрешить запрос OPTIONS и отправить ответ с заголовками Access-Control-Allow-Origin, Access-Control-Allow-Headers и Access-Control-Allow-Methods, разрешающими запрос.Затем браузер выполнит фактический запрос POST.

9 голосов
/ 25 сентября 2014

У меня возникла именно эта проблема из кода JavaScript, который отправлял контент ajax.

Чтобы разрешить запрос перекрестного происхождения с предпечатной проверкой, я должен был сделать это в .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.

Надеюсь, это послужит кому-то в будущем.

2 голосов
/ 11 сентября 2017

Как уже отмечали другие, это вещь CORS.

Вот как это сделать в NGINX (на основе этот источник ):

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 и 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...