В приведенном ниже исследовании в качестве API я использую http://example.com вместо http: // myApiUrl / login из вашего вопроса, потому что этот первый работает.
Я предполагаю, что ваша страница находится на http: //my-site.local: 8088 .
Причина, по которой вы видите разные результаты, заключается в том, что почтальон:
- установить заголовок
Host=example.com
(ваш API)
- НЕ установить заголовок
Origin
Это похоже на способ отправки запросов браузерами, когда сайт и API имеют одинаковый домен (браузеры также устанавливают элемент заголовка Referer=http://my-site.local:8088
, однако я не вижу его в Postman). Когда Origin
заголовок не установлен, обычно серверы разрешают такие запросы по умолчанию.
Это стандартный способ отправки запросов почтальоном. Но браузер отправляет запросы по-разному, когда ваш сайт и API имеют разные домены , а затем происходит CORS и браузер автоматически:
- устанавливает заголовок
Host=example.com
(ваш как API)
- устанавливает заголовок
Origin=http://my-site.local:8088
(ваш сайт)
(Заголовок Referer
имеет то же значение, что и Origin
). Теперь на вкладке « Консоль и сети » Chrome вы увидите:
Когда у вас есть Host != Origin
это CORS, и когда сервер обнаруживает такой запрос, он обычно блокирует его по умолчанию .
Origin=null
устанавливается при открытии содержимого HTML из локального каталога и отправке запроса. Такая же ситуация возникает, когда вы отправляете запрос внутри <iframe>
, как в следующем фрагменте кода (но здесь Host
заголовок вообще не задан) - в общем, везде, где спецификация HTML говорит о непрозрачном происхождении, вы можете перевести это в Origin=null
. Более подробную информацию об этом вы можете найти здесь .
fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab
Если вы не используете простой запрос CORS, обычно браузер автоматически также отправляет запрос OPTIONS перед отправкой основного запроса - дополнительная информация здесь . Фрагмент ниже показывает это:
fetch('http://example.com/api', {
method: 'POST',
headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)
Вы можете изменить конфигурацию вашего сервера, чтобы разрешать запросы CORS.
Вот пример конфигурации, которая включает CORS для nginx (файл nginx.conf) - будьте очень осторожны с настройками always/"$http_origin"
для nginx и "*"
для Apache - это разблокирует CORS из любого домена.
location ~ ^/index\.php(/|$) {
...
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
}
Вот пример конфигурации, которая включает CORS на Apache (файл .htaccess)
# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests |
# ------------------------------------------------------------------------------
# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/
# <IfModule mod_headers.c>
# Header set Access-Control-Allow-Origin "*"
# </IfModule>
# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"
Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"