AJAX в Chrome отправляет ОПЦИИ вместо GET/POST/PUT/DELETE?
Я работаю над внутренним веб-приложением на работе. В IE10 запросы работают нормально, но в Chrome все AJAX-запросы (которых их много) отправляются с использованием OPTIONS вместо любого определенного мной метода. Технически мои запросы являются "междоменными". Сайт обслуживается на localhost:6120, а служба, к которой я обращаюсь к AJAX-запросам, работает на 57124. Эта закрытая ошибка jquery определяет проблему, но не решает ее.
Что я могу сделать, чтобы использовать правильный метод http в запросах ajax?
Редактировать:
Это в документе загрузки каждой страницы:
jQuery.support.cors = true;
И каждый AJAX построен аналогично:
var url = 'http://localhost:57124/My/Rest/Call';
$.ajax({
url: url,
dataType: "json",
data: json,
async: true,
cache: false,
timeout: 30000,
headers: { "x-li-format": "json", "X-UserName": userName },
success: function (data) {
// my success stuff
},
error: function (request, status, error) {
// my error stuff
},
type: "POST"
});
9 ответов
Chrome выполняет предварительный поиск запроса на поиск заголовков CORS. Если запрос приемлем, он отправит реальный запрос. Если вы делаете этот междоменный домен, вам просто придется иметь дело с ним или иначе найти способ сделать запрос не междоменным. Вот почему ошибка jQuery была закрыта как не исправленная. Это по замыслу.
В отличие от простых запросов (обсужденных выше), "предварительно выданные" запросы сначала отправляют HTTP-запрос методом OPTIONS ресурсу в другом домене, чтобы определить, безопасен ли фактический запрос для отправки. Межсайтовые запросы предварительно просматриваются следующим образом, так как они могут иметь значение для пользовательских данных. В частности, запрос предварительно просвечивается, если:
- Он использует методы, отличные от GET, HEAD или POST. Кроме того, если POST используется для отправки данных запроса с Content-Type, отличным от application/x-www-form-urlencoded, multipart/form-data или text/plain, например, если запрос POST отправляет полезную нагрузку XML на сервер используя application/xml или text/xml, запрос предварительно просвечивается.
- Он устанавливает пользовательские заголовки в запросе (например, запрос использует заголовок, такой как X-PINGOTHER)
Исходя из того факта, что запрос не отправляется на порт 80/443 по умолчанию, этот Ajax-вызов автоматически считается запросом ресурса разных источников (CORS), что означает, что запрос автоматически выдает запрос OPTIONS, который проверяет наличие Заголовки CORS на стороне сервера / сервлета.
Это происходит, даже если вы установили
crossOrigin: false;
или даже если вы пропустите это.
Причина в том, что localhost != localhost:57124
, Попробуйте отправить его только localhost
без порта - это не удастся, потому что запрошенная цель не будет достигнута, однако обратите внимание, что если доменные имена равны, запрос отправляется без запроса OPTIONS до POST.
Я согласен с Кевином Б., в сообщении об ошибке все сказано. Похоже, вы пытаетесь совершать междоменные вызовы AJAX. Если вы не знакомы с той же политикой происхождения, вы можете начать здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript.
Если это не предназначено для междоменного вызова ajax, попробуйте сделать ваш целевой URL относительным и посмотреть, исчезнет ли проблема. Если вы действительно отчаянно ищите JSONP, но будьте осторожны, хаос скрывается. На самом деле мы мало что можем сделать, чтобы помочь вам.
В моем случае я вызываю API, размещенный на AWS (API Gateway). Ошибка произошла, когда я попытался вызвать API из домена, отличного от собственного домена API. Поскольку я владелец API, я включил CORS для тестовой среды, как описано в документации Amazon.
В производстве эта ошибка не произойдет, так как запрос и API будут находиться в одном домене.
Я надеюсь, что это помогает!
Если это возможно, передайте параметры через обычный GET/POST с другим именем, и пусть ваш серверный код обрабатывает его.
У меня была похожая проблема с моим собственным прокси, чтобы обойти CORS, и я получил ту же ошибку POST->OPTION в Chrome. Это было Authorization
заголовок в моем случае ("x-li-format"
а также "X-UserName"
здесь, в вашем случае.) Я в конечном итоге передать его в фиктивном формате (например, AuthorizatinJack
в GET), и я изменил код для моего прокси, чтобы превратить его в заголовок при совершении звонка по назначению. Вот это в PHP:
if (isset($_GET['AuthorizationJack'])) {
$request_headers[] = "Authorization: Basic ".$_GET['AuthorizationJack'];
}
Я столкнулся с очень похожей проблемой. Я потратил почти полдня, чтобы понять, почему все работает правильно в Firefox и не работает в Chrome. В моем случае это было из-за дублированных (или, возможно, опечаток) полей в заголовке моего запроса.
"предварительно выданные" запросы сначала отправляют HTTP-запрос методом OPTIONS ресурсу в другом домене, чтобы определить, является ли фактический запрос безопасным для отправки. Межсайтовые запросы
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Как ответил @Dark Falcon, я просто с этим справился.
В моем случае я использую сервер node.js и создаю сеанс, если он не существует. Так как метод OPTIONS не содержит подробностей сеанса, он в конечном итоге создал новый сеанс для каждого запроса метода POST.
Так что в моей подпрограмме приложения create-session-if-not-there я просто добавил проверку, чтобы проверить, является ли метод OPTIONS
и, если это так, просто пропустите часть создания сеанса:
app.use(function(req, res, next) {
if (req.method !== "OPTIONS") {
if (req.session && req.session.id) {
// Session exists
next();
}else{
// Create session
next();
}
} else {
// If request method is OPTIONS, just skip this part and move to the next method.
next();
}
}
Рассмотрите возможность использования Axios
axios.get( url,
{ headers: {"Content-Type": "application/json"} } ).then( res => {
if(res.data.error) {
} else {
doAnything( res.data )
}
}).catch(function (error) {
doAnythingError(error)
});
У меня была эта проблема с использованием fetch и Axios работал отлично.
Используйте fetch вместо XHR, тогда запрос не будет предварительно подсвечен, даже если он является кросс-доменным.
$.ajax({
url: '###',
contentType: 'text/plain; charset=utf-8',
async: false,
xhrFields: {
withCredentials: true,
crossDomain: true,
Authorization: "Bearer ...."
},
method: 'POST',
data: JSON.stringify( request ),
success: function (data) {
console.log(data);
}
});
contentType: 'текст / простой; charset=utf-8'или просто contentType: 'text/plain'у меня работает! С уважением!!