Почему я получаю запрос OPTIONS вместо запроса GET?

<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>

он выполняет запрос OPTIONS к этому URL-адресу, а затем обратный вызов никогда не вызывается ни с чем.

Когда это не кросс-домен, он работает нормально.

Разве jQuery не должен просто выполнять вызов с помощью узла <script>, а затем выполнять обратный вызов при его загрузке? Я понимаю, что не смогу получить результат (так как это кросс-домен), но это нормально; Я просто хочу, чтобы звонок прошел. Это ошибка или я что-то не так делаю?


person Paul Tarjan    schedule 10.08.2009    source источник
comment
Может быть из-за перекрестного домена. Например, если вы используете свой файл File: // PATH_TO_WEBSITE вместо localhost / WEBSITE_LINK   -  person James111    schedule 22.12.2015


Ответы (10)


Согласно MDN,

Предварительные запросы

В отличие от простых запросов (обсужденных выше), «предварительные» запросы сначала отправляют заголовок запроса HTTP OPTIONS к ресурсу в другом домене, чтобы определить, безопасен ли фактический запрос для отправки. Межсайтовые запросы предварительно обрабатываются таким образом, поскольку они могут иметь последствия для пользовательских данных. В частности, предварительная отправка запроса выполняется, если:

  • Он использует методы, отличные от GET или POST. Кроме того, если POST используется для отправки данных запроса с Content-Type, отличным от application / x-www-form-urlencoded, multipart / form-data или text / plain, например если запрос POST отправляет полезные данные XML на сервер с использованием application / xml или text / xml, то запрос выполняется заранее.
  • Он устанавливает настраиваемые заголовки в запросе (например, запрос использует заголовок, такой как X-PINGOTHER)
person arturgrigor    schedule 23.10.2012
comment
это устранило нашу проблему, переход с application / json на text / plain остановил ужасный запрос параметров - person Keeno; 12.07.2013
comment
чего я не понимаю, так это того, почему браузер запрашивает метод OPTIONS только для проверки того, что фактический запрос безопасен для отправки. но в каком смысле? Я имею в виду, что сервер также может накладывать ограничения на определенные заголовки ответов, так зачем это нужно? - person hardik; 03.07.2014
comment
@hardik Помните, что, добавляя CORS, вы потенциально принимаете запросы от всех, в которых они могут манипулировать данными на вашем сервере с помощью запросов (POST, PUT, DELETE и т. д.). В этих ситуациях, например, при использовании настраиваемых заголовков, браузер сначала просто проверяет с сервером, готов ли сервер принять запрос, прежде чем отправлять его, поскольку отправка незапрошенных запросов на сервер может быть действительно опасной для ваших данных, а также что точка в браузере, отправляющая потенциально большие полезные данные, если сервер не хочет их принимать, следовательно, предварительная проверка OPTIONS. - person davidnknight; 19.08.2014
comment
@davidnknight, если отправка ваших данных на сервер может быть опасной, то есть сервер может быть скомпрометирован, тогда, конечно, злонамеренный сервер ответит на ваш запрос OPTIONS с помощью Sure, send it all !. Как там безопасность? (честный вопрос) - person Matt; 30.06.2016
comment
предполетные запросы не связаны с безопасностью. Скорее, они не меняют правил. - См. Ответ на вопрос Какова мотивация введения предварительных запросов < / а> - person FMJaguar; 20.01.2017
comment
как отправить пользовательский заголовок X-Authentication, содержащий токен, без отправки OPTIONS? - person Michail Michailidis; 05.02.2017
comment
Вы, ребята, можете просто проверить ОПЦИИ в своем коде (прежде всего, другие правила) и просто вернуть на него ответ 200. - person Vahid Amiri; 06.08.2017
comment
Вся спецификация CORS странная: какой смысл запрещать настраиваемые заголовки, если разработчики основных API в результате перемещают их на URL-адрес в качестве параметра запроса? Эта спецификация не очень хорошо адаптирована к реальности или наоборот. - person B M; 23.09.2017
comment
Предварительная проверка используется для проверки того, что сервер ожидает нестандартные запросы из разных источников. Запросы XHR (ajax) могут отправлять запросы, которые браузеры не могут отправлять в противном случае (например, PUT, DELETE). CORS предназначен для предотвращения косвенных атак на ваш сервер с использованием браузеров посетителей на сторонних сайтах. - person Mikko Rantalainen; 28.09.2017

ОПЦИИ взяты из http://www.w3.org/TR/cors/ См. http://metajack.im/2010/01/19/crossdomain-ajax-for-xmpp-http-binding-made-easy/ для получения дополнительной информации.

person Paul Tarjan    schedule 24.08.2009

Если вы пытаетесь POST

Обязательно 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"
    });
}
person Derek Soike    schedule 05.04.2017

Я не верю, что jQuery естественным образом выполнит запрос JSONP, если ему будет предоставлен такой URL-адрес. Однако он выполнит запрос JSONP, когда вы сообщите ему, какой аргумент использовать для обратного вызова:

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

Использование этого аргумента полностью зависит от сценария-получателя (который не должен называться «jsoncallback»), поэтому в этом случае функция никогда не будет вызвана. Но, поскольку вы заявили, что просто хотите, чтобы скрипт на metaward.com был выполнен, этого будет достаточно.

person VoteyDisciple    schedule 10.08.2009
comment
будет ли МОЙ обратный вызов по-прежнему получать уведомление о том, что элемент скрипта полностью загружен? Я просто хочу убедиться, что обновление произошло, прежде чем я буду запрашивать его у API. - person Paul Tarjan; 11.08.2009
comment
Вы сделаете это, если принимающий сценарий поддерживает JSONP и желает вызвать функцию, которую вы определяете. Если сценарий ничего не делает, кроме генерирования блока данных JSON без какого-либо другого поведения, вы не сможете определить, когда он загрузился. Если важно знать, когда загрузка завершилась, вы можете рассмотреть возможность реализации сценария на своем собственном сервере, который действует как прокси. - person VoteyDisciple; 11.08.2009

Фактически, междоменные запросы AJAX (XMLHttp) не разрешены из-за соображений безопасности (подумайте о том, чтобы получить "ограниченную" веб-страницу со стороны клиента и отправить ее обратно на сервер - это будет проблемой безопасности).

Единственный обходной путь - обратные вызовы. Это: создание нового объекта сценария и указание src на конечный JavaScript, который является обратным вызовом со значениями JSON (myFunction ({data}), myFunction - это функция, которая что-то делает с данными (например, сохраняет их в переменной).

person Adrián Navarro    schedule 10.08.2009
comment
верно, но я могу загрузить его с помощью ‹скрипта src =› или ‹img src =›, и браузер с радостью откроет его. Я просто хочу знать, когда он полностью загружен, чтобы я мог запросить результат импорта. - person Paul Tarjan; 11.08.2009

Просто измените «application / json» на «text / plain» и не забудьте JSON.stringify (запрос):

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,
    });
person David Lopes    schedule 22.09.2017

У меня такая же проблема. Мое исправление заключалось в добавлении заголовков в мой PHP-скрипт, которые присутствуют только в среде разработки.

Это позволяет выполнять междоменные запросы:

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

Это сообщает предварительному запросу, что клиент может отправлять любые заголовки, которые он хочет:

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

Таким образом, нет необходимости изменять запрос.

Если у вас есть конфиденциальные данные в базе данных разработчиков, которые потенциально могут быть пропущены, подумайте дважды.

person fivebit    schedule 21.02.2018

В моем случае проблема не была связана с CORS, поскольку я отправлял JQuery POST на тот же веб-сервер. Данные были в формате JSON, но я пропустил параметр dataType: 'json'.

У меня не было (и я не добавил) параметра contentType, как показано в ответе Дэвида Лопеса выше.

person GarDavis    schedule 12.11.2018

Похоже, Firefox и Opera (также протестированные на Mac) не любят кросс-доменность этого (но Safari это устраивает).

Возможно, вам придется вызвать код на стороне локального сервера, чтобы свернуть удаленную страницу.

person helloandre    schedule 10.08.2009

Я смог исправить это с помощью следующих заголовков

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();
});
person obai    schedule 17.07.2019