Ich kann diesen Endpunkt, http://catfacts-api.appspot.com/api/facts?number=99
über Postman ansprechen und er gibt JSON
zurück
Außerdem verwende ich create-react-app und möchte die Einrichtung einer Serverkonfiguration vermeiden.
In meinem Client-Code versuche ich, fetch
zu verwenden, um das Gleiche zu tun, aber ich erhalte den Fehler:
No 'Access-Control-Allow-Origin' header is present on the requested Ressource. Herkunft 'http://localhost:3000' ist daher nicht erlaubt Zugriff. Wenn eine undurchsichtige Antwort Ihren Bedürfnissen entspricht, setzen Sie den Request's Modus auf 'no-cors', um die Ressource mit deaktiviertem CORS abzurufen.
Ich versuche also, ein Objekt an mein Fetch zu übergeben, das CORS deaktiviert, etwa so:
fetch('http://catfacts-api.appspot.com/api/facts?number=99', { mode: 'no-cors'})
.then(blob => blob.json())
.then(data => {
console.table(data);
return data;
})
.catch(e => {
console.log(e);
return e;
});
Interessanterweise ist der Fehler, den ich bekomme, eigentlich ein Syntaxfehler in dieser Funktion. Ich bin mir nicht sicher, ob mein eigentliches "Fetch" kaputt ist, denn wenn ich das Objekt { mode: 'no-cors' } entferne und es mit einer anderen URL versehe, funktioniert es ganz gut.
Ich habe auch versucht, das Objekt "{ mode: 'opaque'}" zu übergeben, aber das gibt den ursprünglichen Fehler von oben zurück.
Ich glaube, alles, was ich tun muss, ist CORS zu deaktivieren. Was übersehe ich?
Das Hinzufügen von mode: 'no-cors'
wird die Dinge nicht auf magische Weise zum Laufen bringen. In der Tat macht es die Dinge noch schlimmer, weil ein Effekt ist es zu sagen, Browser, "Blockieren Sie meine Frontend-JavaScript-Code von Blick auf den Inhalt der Antwort Körper und Header unter allen Umständen. " Natürlich ist das fast nie, was Sie wollen.
Was bei herkunftsübergreifenden Anfragen von Frontend-JavaScript passiert, ist, dass die Browser standardmäßig den Frontend-Code vom Zugriff auf herkunftsübergreifende Ressourcen abhalten. Wenn eine Website Access-Control-Allow-Origin
in ihren Antworten sendet, dann lockern die Browser diese Blockierung und erlauben Ihrem Code den Zugriff auf die Antwort.
Wenn eine Website jedoch keinen Access-Control-Allow-Origin
-Header in ihren Antworten sendet, gibt es keine Möglichkeit, dass Ihr Frontend-Code direkt auf Antworten von dieser Website zugreifen kann. Insbesondere können Sie das nicht beheben, indem Sie mode: 'no-cors'
angeben (in der Tat wird das sicherstellen, dass Ihr Frontend-Code nicht auf den Inhalt der Antwort zugreifen kann).
Eine Sache, die jedoch funktionieren wird, ist, wenn Sie Ihre Anfrage durch einen CORS-Proxy senden, wie dies:
var proxyUrl = 'https://cors-anywhere.herokuapp.com/',
targetUrl = 'http://catfacts-api.appspot.com/api/facts?number=99'
fetch(proxyUrl + targetUrl)
.then(blob => blob.json())
.then(data => {
console.table(data);
document.querySelector("pre").innerHTML = JSON.stringify(data, null, 2);
return data;
})
.catch(e => {
console.log(e);
return e;
});
<pre></pre>
Hinweis: Wenn Sie versuchen, https
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
https://cors-anywhere.herokuapp.com
voranzustellen, stellen Sie ihr stattdessen die URL für Ihre eigene Instanz voran, z.B. https://cryptic-headland-94862.herokuapp.com/https://example.com.http://catfacts-api.appspot.com/api/facts?number=99
über Postman erreichen
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS erklärt, warum Sie zwar mit Postman auf die Antwort zugreifen können, die Browser Ihnen aber keinen ursprungsübergreifenden Zugriff auf die Antwort von Frontend-JavaScript-Code in einer Webanwendung gestatten, es sei denn, die Antwort enthält einen Response-Header "Access-Control-Allow-Origin".
http://catfacts-api.appspot.com/api/facts?number=99 hat keinen "Access-Control-Allow-Origin"-Response-Header, so dass es keine Möglichkeit gibt, dass Ihr Frontend-Code auf die Antwort herkunftsübergreifend zugreifen kann.
Ihr Browser kann die Antwort problemlos abrufen und Sie können sie in Postman und sogar in den Browser-Devtools sehen - aber das bedeutet nicht, dass die Browser sie für Ihren Code freigeben. Das werden sie nicht, weil die Antwort keinen "Access-Control-Allow-Origin"-Header hat. Also müssen Sie stattdessen einen Proxy verwenden, um sie zu erhalten.
Der Proxy stellt die Anfrage an diese Seite, erhält die Antwort, fügt den "Access-Control-Allow-Origin"-Antwort-Header und alle anderen benötigten CORS-Header hinzu und gibt diese dann an Ihren anfragenden Code zurück. Und diese Antwort mit dem hinzugefügten "Access-Control-Allow-Origin"-Header ist das, was der Browser sieht, so dass der Browser Ihren Frontend-Code tatsächlich auf die Antwort zugreifen lässt.mode: 'no-cors'
in der Praxis höchstwahrscheinlich nie verwenden wollen, außer in einigen wenigen Fällen, und selbst dann nur, wenn Sie genau wissen, was Sie tun und welche Auswirkungen das hat. Das liegt daran, dass die Einstellung mode: 'no-cors'
dem Browser eigentlich sagt: "Verhindern Sie unter allen Umständen, dass mein Frontend-JavaScript-Code den Inhalt des Antwortkörpers und der Kopfzeilen einsehen kann. " In den meisten Fällen ist das natürlich nicht das, was Sie wollen.Was die Fälle angeht, in denen Sie die Verwendung von "mode: 'no-cors'`" in Betracht ziehen sollten, finden Sie die Details in der Antwort auf https://stackoverflow.com/questions/39109789/what-limitations-apply-to-opaque-responses/39109790#39109790. Das Wesentliche ist, dass die Fälle sind:
<script>
, <link rel=stylesheet>
, <img>
, <video>
, <audio>
, <object>
, <embed>
, oder <iframe>Element (was funktioniert, weil das Einbetten von Ressourcen über den Ursprung hinweg für diese erlaubt ist) - aber aus irgendeinem Grund wollen oder können Sie das nicht einfach tun, indem Sie das Markup des Dokuments die Ressourcen-URL als
hrefoder
src`-Attribut für das Element verwenden lassen.Ich habe auch versucht, das Objekt { mode: 'opaque'}
zu übergeben.
Es gibt keinen mode: 'opaque'
Anfragemodus - opaque
ist stattdessen nur eine Eigenschaft der Antwort, und Browser setzen diese opaque-Eigenschaft auf Antworten von Anfragen, die mit dem no-cors
-Modus gesendet wurden.
Aber nebenbei bemerkt ist das Wort opak ein ziemlich eindeutiges Signal über die Art der Antwort, die Sie am Ende erhalten: "Opak" bedeutet, dass man sie nicht sehen kann.
Die Lösung für mich war, es einfach serverseitig zu machen
Ich benutzte die C# WebClient
-Bibliothek, um die Daten (in meinem Fall waren es Bilddaten) abzurufen und sie an den Client zurückzuschicken. Wahrscheinlich gibt es etwas sehr ähnliches in der von Ihnen gewählten serverseitigen Sprache.
//Server side, api controller
[Route("api/ItemImage/GetItemImageFromURL")]
public IActionResult GetItemImageFromURL([FromQuery] string url)
{
ItemImage image = new ItemImage();
using(WebClient client = new WebClient()){
image.Bytes = client.DownloadData(url);
return Ok(image);
}
}
Sie können es an Ihren eigenen Anwendungsfall anpassen. Der wichtigste Punkt ist, dass client.DownloadData()
ohne CORS-Fehler funktioniert. Normalerweise gibt es CORS-Probleme nur zwischen Websites, daher ist es in Ordnung, von Ihrem Server aus 'cross-site' Anfragen zu stellen.
Dann ist der React-Fetch-Aufruf so einfach wie:
//React component
fetch(`api/ItemImage/GetItemImageFromURL?url=${imageURL}`, {
method: 'GET',
})
.then(resp => resp.json() as Promise<ItemImage>)
.then(imgResponse => {
// Do more stuff....
)}
Eine sehr einfache Lösung (2 Minuten für die Konfiguration) ist die Verwendung des Pakets local-ssl-proxy von npm
.
Die Benutzung ist ziemlich einfach:
npm install -g local-ssl-proxy
local-server
laufen lassen, maskieren Sie ihn mit dem local-ssl-proxy --source 9001 --target 9000
P.S: Ersetzen Sie --target 9000
durch die -- "Nummer Ihres Ports"
und --source 9001
durch --source "Nummer Ihres Ports +1"