Diese Antwort ist sehr umfangreich und besteht aus drei Teilen:
- So verwenden Sie einen CORS-Proxy, um Probleme mit dem Header "Keine Zugriffssteuerung, Zulassen des Ursprungs" zu umgehen
- So vermeiden Sie den CORS-Preflight
- So beheben Sie das Problem "Access-Control-Allow-Origin-Header darf nicht der Platzhalter sein"
So verwenden Sie einen CORS-Proxy, um Probleme mit dem Header "Keine Zugriffssteuerung, Zulassen des Ursprungs" zu umgehen
Wenn Sie den Server nicht steuern, an den Ihr Frontend-JavaScript-Code eine Anfrage sendet, und das Problem mit der Antwort von diesem Server nur das Fehlen des erforderlichen Access-Control-Allow-OriginHeaders ist, können Sie die Dinge trotzdem zum Laufen bringen - indem Sie die Anfrage über a stellen CORS-Proxy. Um zu zeigen, wie das funktioniert, folgt zunächst ein Code, der keinen CORS-Proxy verwendet:
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?"))
Der Grund, warum der catchBlock dort getroffen wird, ist, dass der Browser verhindert, dass dieser Code auf die Antwort zugreift, von der er zurückkommt https://example.com. Der Grund dafür ist, dass der Antwort der Antwortheader fehlt Access-Control-Allow-Origin.
Hier ist genau das gleiche Beispiel, jedoch nur mit einem hinzugefügten CORS-Proxy:
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?"))
Hinweis: Wenn https://cors-anywhere.herokuapp.com nicht verfügbar oder nicht verfügbar ist, wenn Sie es versuchen, lesen Sie unten, wie Sie Ihren eigenen CORS Anywhere-Server bei Heroku in nur 2-3 Minuten bereitstellen.
Das zweite Code-Snippet oben kann erfolgreich auf die Antwort zugreifen, da die Verwendung der Anforderungs-URL in https://cors-anywhere.herokuapp.com/https://example.com - indem nur die Proxy-URL vorangestellt wird - die Antwort verursacht Anfrage, über diesen Proxy gemacht zu werden, der dann:
- Leitet die Anfrage an weiter
https://example.com.
- Erhält die Antwort von
https://example.com.
- Fügt
Access-Control-Allow-Originder Antwort den Header hinzu.
- Übergibt diese Antwort mit dem hinzugefügten Header an den anfordernden Frontend-Code.
Der Browser ermöglicht dann dem Frontend-Code den Zugriff auf die Antwort, da diese Antwort mit dem Access-Control-Allow-OriginAntwortheader vom Browser angezeigt wird.
Sie können Ihren eigenen Proxy einfach mit Code von https://github.com/Rob--W/cors-anywhere/ ausführen .
Sie können auch einfach Ihren eigenen Proxy für Heroku in nur 2-3 Minuten mit 5 Befehlen bereitstellen:
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
Nachdem Sie diese Befehle ausgeführt haben, wird Ihr eigener CORS Anywhere-Server ausgeführt, z . B. https://cryptic-headland-94862.herokuapp.com/ . Stellen Sie Ihrer Anforderungs-URL also nicht https://cors-anywhere.herokuapp.comdie URL für Ihre eigene Instanz voran, anstatt sie mit einem Präfix zu versehen. Beispiel: https://cryptic-headland-94862.herokuapp.com/https://example.com .
Wenn Sie also versuchen, https://cors-anywhere.herokuapp.com zu verwenden, stellen Sie fest, dass es nicht verfügbar ist (was manchmal der Fall sein wird), sollten Sie ein Heroku-Konto einrichten (falls Sie dies noch nicht getan haben) und 2 nehmen oder 3 Minuten, um die oben genannten Schritte auszuführen und Ihren eigenen CORS Anywhere-Server auf Heroku bereitzustellen.
Unabhängig davon, ob Sie Ihre eigene ausführen oder https://cors-anywhere.herokuapp.com oder einen anderen offenen Proxy verwenden, funktioniert diese Lösung auch dann, wenn die Anforderung Browser dazu veranlasst, eine CORS-Preflight- OPTIONSAnforderung auszuführen. In diesem Fall ist die Der Proxy sendet auch die Access-Control-Allow-Headersund Access-Control-Allow-MethodsHeader zurück, die für den erfolgreichen Preflight erforderlich sind.
So vermeiden Sie den CORS-Preflight
Der Code in der Frage löst einen CORS-Preflight aus, da er einen AuthorizationHeader sendet .
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
Auch ohne das Content-Type: application/jsonwürde der Header auch den Preflight auslösen.
Was "Preflight" bedeutet: Bevor der Browser POSTden Code in der Frage versucht, sendet er zuerst eine OPTIONSAnfrage an den Server, um festzustellen, ob der Server sich dafür entscheidet, einen Cross-Origin zu erhalten POST, der die Header Authorizationund enthält Content-Type: application/json.
Es funktioniert ziemlich gut mit einem kleinen Curl-Skript - ich bekomme meine Daten.
Um ordnungsgemäß zu testen curl, müssen Sie die Preflight- OPTIONSAnforderung emulieren, die der Browser sendet:
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"
… Mit https://the.sign_in.urlersetzt durch was auch immer Ihre tatsächliche sign_inURL ist.
Die Antwort, die der Browser auf diese OPTIONSAnfrage sehen muss , muss folgende Header enthalten:
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
Wenn die OPTIONSAntwort diese Header nicht enthält, stoppt der Browser genau dort und versucht nicht einmal, die POSTAnfrage zu senden . Außerdem muss der HTTP-Statuscode für die Antwort 2xx sein - normalerweise 200 oder 204. Wenn es sich um einen anderen Statuscode handelt, stoppt der Browser genau dort.
Der Server in der Frage antwortet auf die OPTIONSAnfrage mit einem 501-Statuscode, was anscheinend bedeutet, dass er angibt, dass er keine Unterstützung für OPTIONSAnfragen implementiert . Andere Server antworten in diesem Fall normalerweise mit dem Statuscode 405 "Methode nicht zulässig".
Sie können also niemals POSTAnfragen von Ihrem Frontend-JavaScript-Code direkt an diesen Server stellen, wenn der Server auf diese OPTIONSAnfrage mit einem 405 oder 501 oder etwas anderem als 200 oder 204 antwortet oder wenn er nicht mit den erforderlichen Antworten antwortet Antwortheader.
Der Weg, um zu vermeiden, dass ein Preflight für den Fall in der Frage ausgelöst wird, wäre:
- Wenn der Server keinen
AuthorizationAnforderungsheader benötigte, sondern sich (zum Beispiel) auf Authentifizierungsdaten stützte, die im Hauptteil der POSTAnforderung oder als Abfrageparameter eingebettet waren
- Wenn der Server nicht verlangt hat, dass der
POSTBody einen Content-Type: application/jsonMedientyp hat, sondern den POSTBody wie application/x-www-form-urlencodedmit einem Parameter namens json(oder was auch immer) akzeptiert, dessen Wert die JSON-Daten sind
So beheben Sie das Problem "Access-Control-Allow-Origin-Header darf nicht der Platzhalter sein"
Ich erhalte eine weitere Fehlermeldung:
Der Wert des Headers 'Access-Control-Allow-Origin' in der Antwort darf nicht der Platzhalter '*' sein, wenn der Anmeldeinformationsmodus der Anforderung 'include' ist. Origin ' http://127.0.0.1:3000 ' ist daher kein Zugriff gestattet. Der Anmeldeinformationsmodus von Anforderungen, die von XMLHttpRequest initiiert wurden, wird durch das Attribut withCredentials gesteuert.
Bei einer Anfrage mit Anmeldeinformationen lassen Browser Ihren Frontend-JavaScript-Code nicht auf die Antwort zugreifen, wenn der Wert des Access-Control-Allow-OriginAntwortheaders lautet *. Stattdessen muss der Wert in diesem Fall genau mit dem Ursprung Ihres Frontend-Codes übereinstimmen http://127.0.0.1:3000.
Siehe Anforderungen und Platzhalter für Anmeldeinformationen im Artikel zur MDN-HTTP-Zugriffssteuerung (CORS).
Wenn Sie den Server steuern, an den Sie die Anforderung senden, können Sie diesen Fall häufig so konfigurieren, dass der Wert des OriginAnforderungsheaders übernommen und in den Wert des Access-Control-Allow-OriginAntwortheaders zurückgeführt wird. Zum Beispiel mit nginx:
add_header Access-Control-Allow-Origin $http_origin
Aber das ist nur ein Beispiel; Andere (Web-) Serversysteme bieten ähnliche Möglichkeiten, um Ursprungswerte wiederzugeben.
Ich benutze Chrome. Ich habe auch versucht, dieses Chrome CORS-Plugin zu verwenden
Dieses Chrome CORS-Plugin fügt anscheinend einfach einen Access-Control-Allow-Origin: *Header in die Antwort ein, die der Browser sieht. Wenn das Plugin intelligenter wäre, würde es den Wert dieses gefälschten Access-Control-Allow-OriginAntwortheaders auf den tatsächlichen Ursprung Ihres Frontend-JavaScript-Codes setzen http://127.0.0.1:3000.
Vermeiden Sie es daher, dieses Plugin auch zum Testen zu verwenden. Es ist nur eine Ablenkung. Wenn Sie testen möchten, welche Antworten Sie vom Server erhalten, ohne dass ein Browser sie filtert, sollten Sie curl -Hwie oben beschrieben verwenden.
Soweit der Frontend-JavaScript-Code für die fetch(…)Anfrage in der Frage:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
Entfernen Sie diese Linien. Die Access-Control-Allow-*Header sind Antwort - Header. Sie möchten sie niemals in einer Anfrage senden. Der einzige Effekt besteht darin, einen Browser für einen Preflight auszulösen.