Запрос CORS POST работает из простого javascript, но почему бы не с jQuery? - PullRequest
80 голосов
/ 07 апреля 2011

Я пытаюсь сделать пост-запрос Cross Origin, и я получил его, работающий в простом Javascript, как это:

var request = new XMLHttpRequest();
var params = "action=something";
request.open('POST', url, true);
request.onreadystatechange = function() {if (request.readyState==4) alert("It worked!");};
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.setRequestHeader("Content-length", params.length);
request.setRequestHeader("Connection", "close");
request.send(params);

Но я бы хотел использовать jQuery, но не могу заставить его работать. Вот что я пытаюсь:

$.ajax(url, {
    type:"POST",
    dataType:"json",
    data:{action:"something"}, 
    success:function(data, textStatus, jqXHR) {alert("success");},
    error: function(jqXHR, textStatus, errorThrown) {alert("failure");}
});

Это приводит к отказу. Если кто-нибудь знает, почему jQuery не работает, пожалуйста, сообщите нам всем. Спасибо.

(я использую jQuery 1.5.1 и Firefox 4.0, и мой сервер отвечает правильным заголовком Access-Control-Allow-Origin)

Ответы [ 5 ]

67 голосов
/ 15 апреля 2011

ОБНОВЛЕНИЕ: Как отметил TimK, в jquery 1.5.2 это больше не требуется. Но если вы хотите добавить пользовательские заголовки или разрешить использование учетных данных (имя пользователя, пароль или файлы cookie и т. Д.), Читайте дальше.


Я думаю, что нашел ответ! (4 часа и много ругательств позже)

//This does not work!!
Access-Control-Allow-Headers: *

Вам нужно вручную указать все заголовки, которые вы примете (по крайней мере, так было в FF 4.0 и Chrome 10.0.648.204).

Метод jQuery $ .ajax отправляет заголовок "x-required-with" для всех кросс-доменных запросов (я думаю, что это единственный кросс-домен).

Итак, отсутствующий заголовок, необходимый для ответа на запрос OPTIONS:

//no longer needed as of jquery 1.5.2
Access-Control-Allow-Headers: x-requested-with

Если вы передаете какие-либо не «простые» заголовки, вам нужно будет включить их в свой список (я отправляю еще один):

//only need part of this for my custom header
Access-Control-Allow-Headers: x-requested-with, x-requested-by

Итак, чтобы собрать все воедино, вот мой PHP:

// * wont work in FF w/ Allow-Credentials
//if you dont need Allow-Credentials, * seems to work
header('Access-Control-Allow-Origin: http://www.example.com');
//if you need cookies or login etc
header('Access-Control-Allow-Credentials: true');
if ($this->getRequestMethod() == 'OPTIONS')
{
  header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
  header('Access-Control-Max-Age: 604800');
  //if you need special headers
  header('Access-Control-Allow-Headers: x-requested-with');
  exit(0);
}
15 голосов
/ 08 апреля 2011

Другая возможность заключается в том, что установка dataType: json заставляет JQuery отправлять заголовок Content-Type: application/json.CORS считает это нестандартным заголовком и требует предварительного запроса CORS.Итак, несколько вещей, которые нужно попробовать:

1) Попробуйте настроить сервер так, чтобы он отправлял правильные предварительные ответы.Это будет в виде дополнительных заголовков, таких как Access-Control-Allow-Methods и Access-Control-Allow-Headers.

2) Отбросьте настройку dataType: json.JQuery должен запросить Content-Type: application/x-www-form-urlencoded по умолчанию, но чтобы быть уверенным, вы можете заменить dataType: json на contentType: 'application/x-www-form-urlencoded'

8 голосов
/ 07 апреля 2011

Вы отправляете «params» в js: request.send(params);

, но «data» в jquery ". Определены ли данные ?: data:data,

Также у вас есть ошибка вURL:

$.ajax( {url:url,
         type:"POST",
         dataType:"json",
         data:data, 
         success:function(data, textStatus, jqXHR) {alert("success");},
         error: function(jqXHR, textStatus, errorThrown) {alert("failure");}
});

Вы смешиваете синтаксис с синтаксисом для $ .post


Обновление : я гуглял, основываясь на ответе monsur,и я обнаружил, что вам нужно добавить Access-Control-Allow-Headers: Content-Type (ниже полный абзац)

http://metajack.im/2010/01/19/crossdomain-ajax-for-xmpp-http-binding-made-easy/

Как работает CORS

CORS работает очень похоже наFlash-файл crossdomain.xml. По сути, браузер отправляет междоменный запрос службе, устанавливая HTTP-заголовок Origin на запрашивающий сервер. Служба включает несколько заголовков, таких как Access-Control-Allow-Origin, чтобы указать, является ли такойзапрос разрешен.

Для менеджеров соединений BOSH достаточно указать, что разрешены все источники, установив значение Access-Control-Allow-Origin в *. Заголовок Content-Type также должен бытьбелый список в заголовке Access-Control-Allow-Headers.

Наконец, для определенных типов запросов, включая запросы менеджера соединений BOSH, проверка разрешений будет предварительно проверена.Браузер выполнит запрос OPTIONS и ожидает получить некоторые HTTP-заголовки, которые указывают, какие источники разрешены, какие методы разрешены и как долго будет длиться эта авторизация.Например, вот какие патчи для Пенджаба и Эджаберда, которые я сделал для OPTIONS:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type 
Access-Control-Max-Age: 86400
0 голосов
/ 12 июля 2019

Cors меняет метод запроса до его выполнения, с POST на OPTIONS, поэтому ваши данные не будут отправлены.Способ, который работал для решения этой проблемы cors, - выполнение запроса с помощью ajax, который не поддерживает метод OPTIONS.пример кода:

        $.ajax({
            type: "POST",
            crossdomain: true,
            url: "http://localhost:1415/anything",
            dataType: "json",
            data: JSON.stringify({
                anydata1: "any1",
                anydata2: "any2",
            }),
            success: function (result) {
                console.log(result)
            },
            error: function (xhr, status, err) {
                console.error(xhr, status, err);
            }
        });

с этими заголовками на сервере c #:

                    if (request.HttpMethod == "OPTIONS")
                    {
                          response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With");
                          response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
                          response.AddHeader("Access-Control-Max-Age", "1728000");
                    }
                    response.AppendHeader("Access-Control-Allow-Origin", "*");
0 голосов
/ 05 марта 2019

Измените ваш Jquery следующим образом:

$.ajax({
            url: someurl,
            contentType: 'application/json',
            data: JSONObject,
            headers: { 'Access-Control-Allow-Origin': '*' }, //add this line
            dataType: 'json',
            type: 'POST',                
            success: function (Data) {....}
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...