W poniższym dochodzeniu jako API używam http://example.com zamiast http: // myApiUrl / login z twojego pytania, ponieważ to pierwsze działa.
Zakładam, że twoja strona jest na http: //my-site.local: 8088 .
Powodem, dla którego widzisz różne wyniki, jest to, że Listonosz:
- ustaw nagłówek
Host=example.com
(twój API)
- NIE ustawiam nagłówka
Origin
Jest to podobne do sposobu wysyłania żądań przez przeglądarkę, gdy witryna i interfejs API mają tę samą domenę (przeglądarki również ustawiają element nagłówka Referer=http://my-site.local:8088
, ale nie widzę go w Listonoszu). Gdy Origin
nagłówek nie jest ustawiony, zazwyczaj serwery domyślnie dopuszczają takie żądania.
Jest to standardowy sposób, w jaki Listonosz wysyła żądania. Ale przeglądarka wysyła żądania inaczej, gdy witryna i interfejs API mają różne domeny , a następnie występuje CORS i przeglądarka automatycznie:
- ustawia nagłówek
Host=example.com
(twój jako API)
- ustawia nagłówek
Origin=http://my-site.local:8088
(twoja strona)
(Nagłówek Referer
ma taką samą wartość jak Origin
). A teraz na karcie Konsola i sieci Chrome zobaczysz:
Gdy masz Host != Origin
to CORS, a gdy serwer wykryje takie żądanie, zwykle domyślnie je blokuje .
Origin=null
jest ustawiany po otwarciu treści HTML z katalogu lokalnego i wysyła żądanie. Ta sama sytuacja ma miejsce, gdy wysyłasz żądanie wewnątrz <iframe>
, jak w poniższym fragmencie (ale tutaj Host
nagłówek wcale nie jest ustawiony) - ogólnie rzecz biorąc, wszędzie tam, gdzie specyfikacja HTML mówi nieprzejrzyste pochodzenie, możesz to przetłumaczyć Origin=null
. Więcej informacji na ten temat można znaleźć tutaj .
fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab
Jeśli nie korzystasz z prostego żądania CORS, zazwyczaj przeglądarka automatycznie wysyła również żądanie OPTIONS przed wysłaniem żądania głównego - więcej informacji tutaj . Poniższy fragment pokazuje to:
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)
Możesz zmienić konfigurację swojego serwera, aby zezwolić na żądania CORS.
Oto przykładowa konfiguracja, która włącza CORS na nginx (plik nginx.conf) - bądź bardzo ostrożny z ustawieniami always/"$http_origin"
dla nginx i "*"
Apache - spowoduje to odblokowanie CORS z dowolnej domeny.
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;
}
}
Oto przykładowa konfiguracja, która włącza CORS na Apache (plik .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"