Кросс-доменный POST-запрос с использованием кросс-источника общего доступа к ресурсам, не возвращая данные - PullRequest
13 голосов
/ 09 марта 2011

Я отправляю данные между доменами через запрос POST, но ответ не работает, в частности, никогда не вызывается обработчик успеха jQuery.

Используемые материалы: Django, Apache, jQuery.

Итак, я настроил запрос, довольно похожий на этот:

$.ajax({
    url: "http://somesite.com/someplace",
    type: "POST",
    cache: false,
    dataType: "json",
    data: { ... },
    success: function( msg ) {
        alert(msg);
    },
});

Как вы хорошо знаете, CORS позволяет мне ответить на запрос OPTIONS соответствующим образом, чтобы сказать "Да, вы можете отправить мне ".Что я и делаю.Firebug подтверждает, что я получаю свой код состояния 200 и что тип возвращаемого значения на самом деле application/json.Тем не менее, Firebug также подтверждает, что обработчик успеха в приведенном выше примере не вызывается.

Для справки, мой ответ на OPTIONS:

elif request.method == "OPTIONS":
    response = HttpResponse("")
    response['Access-Control-Allow-Origin'] = "*"
    response['Access-Control-Allow-Methods'] = "POST, GET, OPTIONS"
    response['Access-Control-Allow-Headers'] = "X-Requested-With"
    return response

Внапротив, если я установлю обработчик complete: function()..., он будет работать.

Итак, вопрос в том, что происходит (или нет) и почему?Я получаю данные в порядке, я просто хотел бы иметь возможность вернуть ответ.


Обновление : Это исправляет мою проблему в некоторых браузерах, но так как я неУ меня нет полного определенного объяснения этому поведению. Я оставляю его открытым .

Хорошо, поэтому я прочитал руководство и, насколько я понимаю, примененный алгоритмпримерно так:

  1. Пользовательские агенты могут реализовывать предполетный вызов.Это запрос OPTIONS.Идея состоит в том, что они делают этот запрос, который дает им ответ относительно запрошенного ресурса, который они затем должны кешировать. Я не возвращаю поле максимального возраста , поэтому я подозреваю, что пока возвращается успех и X-запрос разрешен, в кеше агента пользователя нет ничего, что позволило бы мне это сделать, поэтомуприменяются правила по умолчанию (изолировать запрос).
  2. Когда вы делаете фактический запрос, я полагаю, что пользовательский агент должен проверять кэш перед полетом на предмет разрешений.Я полагаю, что без моего поля максимального возраста эти разрешения не найдены.Тем не менее, ответ с одинаковыми заголовками на POST, по-видимому, позволяет Firefox и Google Chrome просматривать ответ.Опера не может.IE остается непроверенным на данный момент.

В настоящее время я не понимаю, и из руководства неясно (по крайней мере для меня), должен ли запрос CORS также отвечать с этими заголовками в запросекак OPTIONS.Я поэкспериментирую с заголовком Max-Age и посмотрю, что это позволяет или не позволяет.Тем не менее, мне все еще не хватает определенного авторитетного понимания по этому вопросу, поэтому, если здесь есть кто-то, кто знает, я весь в ушах.

Ответы [ 4 ]

17 голосов
/ 10 марта 2011

Хорошо, так что я считаю, что правильный способ сделать это так:

if request.method == "POST":
    response = HttpResponse(simplejson.dumps(data),mimetype='application/json')
    response['Access-Control-Allow-Origin'] = "*"
    return response
elif request.method == "OPTIONS":
    response = HttpResponse("")
    response['Access-Control-Allow-Origin'] = "*"
    response['Access-Control-Allow-Methods'] = "POST, OPTIONS"
    response['Access-Control-Allow-Headers'] = "X-Requested-With"
    response['Access-Control-Max-Age'] = "1800"
else:
    return HttpResponseBadRequest()

Это основано на документации , которую я выкопал из Mozilla по предварительно выданным запросам.

Итак, я верю, что это произойдет так:

  1. Если в кэше предпечатных данных ничего нет, OPTIONS отправляется с X-Requested-With, установленным в XMLHttpRequest Я считаю, что это необходимо дляразрешить доступ Javascript ко всему, наряду с заголовком Origin.
  2. Сервер может проверить эту информацию. Это безопасность CORS .В моем случае я отвечаю «любой источник сделает» и «вам разрешено отправить вещь X-Requested-With».Я говорю, что OPTIONS и POST разрешены и что этот ответ должен кэшироваться в течение 30 минут.
  3. Затем клиент запускает POST, который работал раньше.
  4. Первоначально я изменил ответ, включив в него Allow-Methods и Allow-Headers, но в соответствии с обменом в вышеупомянутой связанной документации это не требуется.Это имеет смысл, проверка доступа уже сделана.
  5. Я считаю, что то, что происходит, - это проверка совместного использования ресурса , описанная здесь .По сути, после того, как указанный запрос был сделан, браузер снова проверяет правильность поля Allow-Origin, например, по запросу POST.Если это пройдет, клиент может иметь доступ к данным, если нет, запрос уже завершен, но браузер отказывает фактическому клиентскому приложению (Javascript) в доступе к этим данным.

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

1 голос
/ 14 декабря 2012

Для любых будущих пользователей, которые могут столкнуться с этой публикацией, следующим ресурсом является рабочий проект W3C 2008, в котором подробно рассматривается CORS.

http://www.w3.org/TR/2008/WD-access-control-20080912/

На момент написания этой статьи следует отметить, что в Chromium и, вероятно, во всем WebKit есть ошибка, которая не позволяет учитывать значение заголовка Access-Control-Max-Age. Подробности об этом можно найти на странице обсуждения для Chromium Issue 131368 . В итоге - на данный момент браузеры на основе WebKit будут переопределять все, что сервер возвращает в качестве значения, с 600 (10 минут).

0 голосов
/ 06 декабря 2013

ЗАПРОС:

 $.ajax({
            url: "http://localhost:8079/students/add/",
            type: "POST",
            crossDomain: true,
            data: JSON.stringify(somejson),
            dataType: "json",
            success: function (response) {
                var resp = JSON.parse(response)
                alert(resp.status);
            },
            error: function (xhr, status) {
                alert("error");
            }
        });

РЕПЛИКА:

response = HttpResponse(json.dumps('{"status" : "success"}'))
response.__setitem__("Content-type", "application/json")
response.__setitem__("Access-Control-Allow-Origin", "*")

return response
0 голосов
/ 10 марта 2011

Я не думаю, что это возможно по соображениям безопасности. Единственные междоменные вызовы ajax, которые разрешают браузеры, могут быть выполнены с использованием JSONP, и это исключительно запросы GET.

Это будет работать:

$.ajax({
    url: "http://somesite.com/someplace",
    type: "GET",
    cache: false,
    dataType: "JSONP",
    data: { ... },
    success: function( msg ) {
        alert(msg);
    },
});

Это не будет:

$.ajax({
    url: "http://somesite.com/someplace",
    type: "POST",
    cache: false,
    dataType: "JSONP",
    data: { ... },
    success: function( msg ) {
        alert(msg);
    },
});
...