Нет заголовка "Access-Control-Allow-Origin" на запрошенном ресурсе-при попытке получить данные из REST API
Я пытаюсь получить некоторые данные из REST API HP Alm. Он отлично работает с небольшим скриптом curl - я получаю свои данные.
теперь, делая это с JavaScript, fetch и ES6 (более или менее), кажется, большая проблема. Я продолжаю получать это сообщение об ошибке:
Fetch API не может загрузить . Ответ на запрос preflight не проверка контроля доступа пропуска: нет заголовка "Access-Control-Allow-Origin" присутствует на запрашиваемый ресурс. Происхождение 'http://127.0.0.1:3000 ' is поэтому доступ запрещен. Ответ имел код состояния HTTP 501. Если непрозрачный ответ служит вашим потребностям, установите режим запроса в 'no-cors', чтобы получить ресурс с отключенным CORS.
Я понимаю, что это потому, что я пытаюсь получить эти данные из моего localhost, и решение должно использовать CORS. Теперь я думал, что действительно сделал это, но каким-то образом он либо игнорирует то, что я пишу в заголовке, либо проблема в чем-то другом?
Итак, есть ли проблема с реализацией? Я делаю это неправильно? К сожалению, я не могу проверить журналы сервера. Я действительно немного застрял здесь.
function performSignIn() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
headers.append('GET', 'POST', 'OPTIONS');
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
fetch(sign_in, {
//mode: 'no-cors',
credentials: 'include',
method: 'POST',
headers: headers
})
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log('Authorization failed : ' + error.message));
}
Я использую Chrome. Я также попытался использовать этот плагин Chrome CORS, но затем я получаю другое сообщение об ошибке:
значение заголовка "Access-Control-Allow-Origin" в ответе не должно быть подстановочного знака"*", когда режим учетных данных запроса "включить". Происхождение'http://127.0.0.1:3000 ' поэтому не допускается доступ. Режим учетных данных запросов, инициированных XMLHttpRequest управляется атрибутом withCredentials.
4 ответов
этот ответ охватывает много земли, поэтому он разделен на три части:
- Как избежать CORS предполетного
- как использовать прокси-сервер CORS, чтобы обойти "нет заголовка Access-Control-Allow-Origin" проблемы
- как исправить "заголовок Access-Control-Allow-Origin не должен быть подстановочным знаком" проблемы
Как избежать CORS предполетного
код в вопросе запускается предварительный запуск CORS-так как он отправляет .
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
даже без этого Content-Type: application/json
заголовок также вызовет предполетную подготовку.
что означает" предполетный": прежде чем браузер попытается POST
в коде в вопросе он сначала отправит OPTIONS
запрос на сервер-чтобы определить, является ли сервер выбор в получении перекрестного происхождения POST
это включает в себя Authorization
и Content-Type: application/json
заголовки.
он работает довольно хорошо с небольшим скриптом curl - я получаю свои данные.
для правильного тестирования с curl
, вам нужно эмулировать предполетный OPTIONS
запрос браузер отправляет:
curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type, Authorization' \
"https://the.sign_in.url"
...С https://the.sign_in.url
заменен на любой ваш фактический sign_in
URL-адреса.
ответ, который браузер должен видеть из этого OPTIONS
запрос должен включать такие заголовки:
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
если OPTIONS
ответ не включает эти заголовки, тогда браузер остановится прямо там и даже не попытается отправить POST
запрос. Кроме того, код состояния HTTP для ответа должен быть 2xx-обычно 200 или 204. Если это какой-либо другой код состояния, браузер остановится прямо там.
сервер в вопросе отвечает на OPTIONS
запрос с кодом состояния 501, что, по-видимому, означает он пытается указать, что он не реализует поддержку OPTIONS
запросы. В этом случае другие серверы обычно отвечают кодом состояния 405 "метод не разрешен".
так что вы никогда не сможете сделать POST
запрашивает непосредственно на этот сервер из вашего интерфейсного кода JavaScript, если сервер отвечает на это OPTIONS
запрос с 405 или 501 или что-либо, кроме 200 или 204, или если не отвечает с этими необходимыми заголовками ответов.
путь к избегайте запуска предполетного режима для случая в вопросе:
- если сервер не требует
Authorization
заголовок запроса, но вместо этого (например) полагался на данные аутентификации, встроенные в телоPOST
запрос или запрос с параметрами - если сервер не требует
POST
тело, чтобы иметьContent-Type: application/json
тип носителя, но вместо этого принялPOST
телоapplication/x-www-form-urlencoded
с параметром (или что-то еще) чье значение является JSON данные
как использовать прокси CORS, чтобы обойти "нет заголовка Access-Control-Allow-Origin" проблемы
если вы не контролируете сервер, ваш интерфейс JavaScript-код отправляет запрос, и проблема с ответом от этого сервера - это просто отсутствие необходимого Access-Control-Allow-Origin
заголовок, вы все еще можете заставить вещи работать-сделав запрос через прокси-сервер CORS. Чтобы показать, как это работает, вот код это не использует прокси-сервер CORS:
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
причина catch
блок попадает туда, браузер предотвращает доступ этого кода к ответу, который возвращается из https://example.com
. И причина, по которой браузер делает это, заключается в том, что ответу не хватает Access-Control-Allow-Origin
заголовок ответа.
теперь, вот точно такой же пример, но только с добавленным прокси-сервером CORS:
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(proxyurl + url) // https://cors-anywhere.herokuapp.com/https://example.com
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
Примечание.: Если https://cors-anywhere.herokuapp.com не работает или недоступен при попытке, а затем см. ниже, как развернуть свой собственный сервер CORS Anywhere на Heroku всего за 2-3 минуты.
второй фрагмент кода выше может успешно получить доступ к ответу, потому что принимает URL-адрес запроса и изменяет его наhttps://cors-anywhere.herokuapp.com/https://example.com - просто префиксом его с URL-адресом прокси-вызывает запрос на получение через этот прокси-сервер, который затем:
- перенаправляет запрос на
https://example.com
. - получает ответ от
https://example.com
. - добавляет
Access-Control-Allow-Origin
заголовок ответа. - передает этот ответ с добавленным заголовком обратно в запрашивающий код интерфейса.
браузер затем позволяет интерфейсному коду получить доступ к ответу, потому что этот ответ с Access-Control-Allow-Origin
заголовок ответа-это то, что видит браузер.
вы можете легко запустить свой собственный прокси-сервер с помощью кода изhttps://github.com/Rob--W/cors-anywhere/.
Вы также можете легко развернуть свой собственный прокси в Heroku буквально за 2-3 минуты, с 5 командами:
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
после выполнения этих команд вы получите свой собственный сервер CORS Anywhere, работающий, например,https://cryptic-headland-94862.herokuapp.com/. Таким образом, вместо префикса URL-адреса запроса с https://cors-anywhere.herokuapp.com
, префикс его вместо URL для вашего собственного примера; например, https://cryptic-headland-94862.herokuapp.com/https://example.com.
поэтому, если вы идете, чтобы попытаться использовать https://cors-anywhere.herokuapp.com, вы обнаружите, что это вниз (что иногда будет), затем рассмотрите возможность получения учетной записи Heroku (если вы еще этого не сделали) и выполните 2 или 3 минуты, чтобы выполнить вышеуказанные шаги для развертывания собственного сервера CORS Anywhere на Heroku.
независимо от того, работаете ли вы самостоятельно или используете https://cors-anywhere.herokuapp.com или другой открытый прокси-сервер, это решение будет работать, даже если запрос является тем, который запускает браузеры, чтобы сделать CORS preflight OPTIONS
request-потому что в этом случае прокси также отправляет обратно Access-Control-Allow-Headers
и Access-Control-Allow-Methods
заголовки, необходимые для успешной предполетной подготовки.
как исправить "заголовок Access-Control-Allow-Origin не должен быть подстановочным знаком" проблемы
я получение другого сообщения об ошибке:
значение заголовка "Access-Control-Allow-Origin" в ответе не должно быть подстановочного знака"*", когда режим учетных данных запроса "включить". Происхождение'http://127.0.0.1:3000 ' поэтому не допускается доступ. Режим учетных данных запросов, инициированных XMLHttpRequest управляется атрибутом withCredentials.
для запроса, который включает учетные данные, браузеры не позволят вашему интерфейсному коду JavaScript получить доступ к ответу, если значение Access-Control-Allow-Origin
заголовок ответа *
. Вместо этого значение в этом случае должно точно соответствовать исходному коду вашего интерфейса,http://127.0.0.1:3000
.
посмотреть учетные запросы и подстановочные знаки в статье MDN HTTP access control (CORS).
если вы управляете сервером вы отправляете запрос, то общий способ справиться с этим делом в настроить сервер, чтобы принять значение Origin
заголовок запроса и Эхо / отражают это обратно в значение Access-Control-Allow-Origin
заголовок ответа. Например, в nginx:
add_header Access-Control-Allow-Origin $http_origin
но это только один пример; другие (веб) серверные системы предоставляют аналогичные способы Эхо-значений происхождения.
я использую Chrome. Я также попытался использовать этот плагин Chrome CORS
что CORS хром плагин, видимо, просто simplemindedly впрыскивает Ан Access-Control-Allow-Origin: *
заголовок в ответ, который видит браузер. Если бы плагин был умнее, то, что он будет делать, это установка значения этой подделки Access-Control-Allow-Origin
заголовок ответа на фактическое происхождение вашего интерфейса JavaScript-кода,http://127.0.0.1:3000
.
поэтому избегайте использования этого плагина, даже для тестирования. Это просто отвлекающий маневр. Если вы хотите проверить, какие ответы вы получаете от сервера без фильтрации браузером, вам лучше использовать curl -H
как выше.
насколько интерфейсный код JavaScript для fetch(…)
запрос в вопрос:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
удалите эти строки. The Access-Control-Allow-*
заголовки ответ заголовки. Вы никогда не хотите отправить их в запросе. Единственный эффект, который будет иметь, чтобы вызвать браузер, чтобы сделать предпечатную.
эта ошибка возникает, когда URL-адрес клиента и URL-адрес сервера не совпадают, включая номер порта. В этом случае вам нужно включить службу для CORS, которая является общим доступом к ресурсам cross origin.
Если вы размещаете сервис весеннего отдыха, вы можете найти его в блоге поддержка CORS в Spring Framework.
Если вы размещаете службу с помощью узла.сервер JS тогда
- остановить узел.Яш сервер.
- npm установить cors
-
добавьте на сервер следующие строки.js
var cors = require('cors') app.use(cors()) // Use this after the variable declaration
использовать тип данных: 'jsonp', работает для меня.
async function get_ajax_data(){
var _reprojected_lat_lng = await $.ajax({
type: 'GET',
dataType: 'jsonp',
data: {},
url: _reprojection_url,
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR)
},
success: function (data) {
console.log(data);
// note: data is already json type, you just specify dataType: jsonp
return data;
}
});
} // function