Заголовок "Access-Control-Allow-Origin" отсутствует на запрошенном ресурсе-при попытке получить данные из REST API
Я пытаюсь извлечь некоторые данные из REST API HP Alm. Он довольно хорошо работает с небольшим скриптом curl - я получаю свои данные.
теперь делать это с JavaScript, fetch и ES6 (более или менее), кажется, большая проблема. Я продолжаю получать это сообщение об ошибке:
Fetch API не удается загрузить . Ответ на предварительный запрос не проверка контроля допуска пропуска: никакой заголовок 'Access-Control-Allow-Origin' присутствует на запрашиваемый ресурс. Происхождение - http://127.0.0.1:3000 ' is поэтому доступ запрещен. Ответ имел код состояния HTTP 501. Если непрозрачный ответ удовлетворяет вашим требованиям, установите режим запроса в значение 'no-cors' для извлечения ресурса с отключенным CORS.
Я понимаю, что это потому, что я пытаюсь извлечь эти данные из моего локального хоста, и решение должно использовать 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 preflight-так как он отправляет .
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
запрос-потому что в этом случае, прокси-сервер также отправляет обратно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
этот плагин Chrome CORS, по-видимому, просто простодушно вводит Ан
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');
удалите эти строки. Элемент
Access-Control-Allow-*
заголовки ответ заголовки. Вы никогда не хотите, чтобы отправить их в запрос. Единственный эффект, который будет иметь это вызвать браузер, чтобы сделать предполетный.
эта ошибка возникает, когда URL-адрес клиента и URL-адрес сервера не совпадают, включая номер порта. В этом случае вам нужно включить службу для CORS, которая является общим ресурсом cross origin.
Если вы размещаете сервис весеннего отдыха, то вы можете найти его в блоге поддержка CORS в Spring Framework.
Если вы размещаете службу с помощью узла.сервер JS тогда
- остановить узел.js сервер.
- npm install 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