wake-up-neo.com

Versuch, den Abruf- und Übergabemodus zu verwenden: no-cors

Ich kann diesen Endpunkt http://catfacts-api.appspot.com/api/facts?number=99 über Postman erreichen und er gibt JSON zurück.

Zusätzlich verwende ich create -rease-app und möchte die Einrichtung einer Server-Konfiguration vermeiden.

In meinem Client-Code versuche ich, fetch für dasselbe zu verwenden, aber ich erhalte den Fehler:

Auf dem angeforderten .__-Header ist kein 'Access-Control-Allow-Origin'-Header vorhanden. Ressource. Origin ' http: // localhost: 3000 ' ist daher nicht zulässig Zugriff. Wenn eine undurchsichtige Antwort Ihren Anforderungen entspricht, setzen Sie die Anforderung Modus auf 'no-cors', um die Ressource bei deaktiviertem CORS abzurufen.

Also versuche ich, ein Objekt an meinen Fetch zu übergeben, der CORS deaktiviert, wie folgt:

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 erhalte, tatsächlich ein Syntaxfehler bei dieser Funktion. Ich bin nicht sicher, ob meine fetch defekt ist, denn wenn ich das {mode: 'no-cors'} - Objekt entferne und es mit einer anderen URL versende, funktioniert es einwandfrei.

Ich habe auch versucht, das Objekt { mode: 'opaque'} zu übergeben, aber dies gibt den ursprünglichen Fehler von oben zurück.

Ich glaube, alles was ich tun muss, ist das Deaktivieren von CORS. Was fehlt mir?

54
dwww

Wenn Sie mode: 'no-cors' Hinzufügen, funktioniert das nicht auf magische Weise. Tatsächlich macht es die Sache noch schlimmer, denn ein Effekt besteht darin, den Browsern mitzuteilen, "dass mein Frontend-JavaScript-Code unter keinen Umständen den Inhalt des Antworttextes und der Header anzeigen darf."Of natürlich ist das fast nie was du willst.

Bei Cross-Origin-Anfragen von Frontend-JavaScript blockieren Browser standardmäßig den Frontend-Code für den Zugriff auf Ressourcen von Cross-Origin. Wenn eine Site in ihren Antworten Access-Control-Allow-Origin Sendet, lockern die Browser diese Blockierung und erlauben Ihrem Code, auf die Antwort zuzugreifen.

Wenn eine Site jedoch keinen Access-Control-Allow-Origin - Header in ihren Antworten sendet, kann Ihr Frontend-Code auf keinen Fall direkt auf die Antworten dieser Site zugreifen. Insbesondere können Sie das Problem nicht beheben, indem Sie mode: 'no-cors' Angeben (in der Tat wird durch sichergestellt, dassIhr Frontend-Code nicht auf den Inhalt der Antwort zugreifen kann).

Allerdings ist eine Sache, die funktionieren wird, wenn Sie Ihre Anfrage über einen CORS-Proxy senden, wie folgt:

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://cors-anywhere.herokuapp.com zu verwenden, stellen Sie fest, dass es nicht funktioniert , können Sie es auch problemlos bereitstellen Ihren eigenen Proxy zu Heroku in nur 2-3 Minuten, mit 5 Befehlen:

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 beispielsweise unter https://cryptic-headland-94862.herokuapp.com/ ausgeführt. Anstatt also Ihrer Anforderungs-URL das Präfix https://cors-anywhere.herokuapp.com Voranzustellen, stellen Sie ihr stattdessen die URL für Ihre eigene Instanz voran. beispielsweise https://cryptic-headland-94862.herokuapp.com/https://example.com .


Ich kann diesen Endpunkt 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 Browser gewonnen haben, obwohl Sie mit Postman auf die Antwort zugreifen können Der Zugriff auf die Antwort ist über den in einer Webanwendung ausgeführten JavaScript-Frontend-Code nur möglich, wenn die Antwort einen Antwortheader Access-Control-Allow-Origin enthält.

http://catfacts-api.appspot.com/api/facts?number=99 hat keinen Access-Control-Allow-Origin - Antwortheader, daher kann Ihr Frontend-Code nicht verwendet werden Zugriff auf die Antwort Herkunftsübergreifend.

Ihr Browser kann die Antwort in Ordnung bringen, und Sie können sie in Postman und sogar in Browser-Entwicklungstools sehen. Dies bedeutet jedoch nicht, dass Browser sie Ihrem Code aussetzen. Sie werden es nicht tun, da es keinen Access-Control-Allow-Origin - Antwortheader gibt. Sie müssen stattdessen einen Proxy verwenden, um ihn abzurufen.

Der Proxy sendet die Anforderung an diese Site, erhält die Antwort, fügt den Antwortheader Access-Control-Allow-Origin Und alle anderen erforderlichen CORS-Header hinzu und leitet diesen an Ihren anfordernden Code zurück. Und diese Antwort mit dem hinzugefügten Header Access-Control-Allow-Origin Wird vom Browser angezeigt, sodass Ihr Frontend-Code tatsächlich auf die Antwort zugreifen kann.


Ich versuche also, ein Objekt an meinen Fetch zu übergeben, das CORS deaktiviert

Das willst du nicht. Um es klar auszudrücken: Wenn Sie sagen, Sie möchten CORS deaktivieren, meinen Sie anscheinend tatsächlich, Sie möchten die Richtlinie mit demselben Ursprung deaktivieren . CORS selbst ist eine Möglichkeit, dies zu tun - CORS ist eine Möglichkeit, die Richtlinie für denselben Ursprung zu lockern, nicht eine Möglichkeit, sie einzuschränken.

Es stimmt jedoch, dass Sie - nur in Ihrer lokalen Umgebung - Ihrem Browser Laufzeit-Flags geben können, um die Sicherheit zu deaktivieren und unsicher zu laufen, oder Sie können lokal eine Browser-Erweiterung installieren, um die gleiche Origin-Richtlinie zu umgehen ist die Situation nur für Sie vor Ort zu ändern.

Unabhängig davon, was Sie lokal ändern, wird bei jedem anderen Benutzer, der versucht, Ihre App zu verwenden, weiterhin dieselbe Origin-Richtlinie angewendet. Auf keinen Fall können Sie diese für andere Benutzer Ihrer App deaktivieren.

Sie möchten höchstwahrscheinlich nie mode: 'no-cors' In der Praxis verwenden, außer in einigen wenigen Fällen , und selbst dann nur, wenn Sie genau wissen, was Sie tun machst und was die auswirkungen sind. Dies liegt daran, dass die Einstellung mode: 'no-cors' Dem Browser tatsächlich Folgendes sagt: "Blockiere meinen Frontend-JavaScript-Code, um unter allen Umständen in den Inhalt des Antworttextes und der Header zu schauen."In den meisten Fällen ist das offensichtlich wirklich nicht das, was Sie wollen.


In den Fällen, in denen Sie in Betracht ziehen würden, mode: 'no-cors' Zu verwenden, lesen Sie die Antwort unter Welche Einschränkungen gelten zu undurchsichtigen Antworten?für die Details. Der Kern davon ist, dass die Fälle sind:

  • Im eingeschränkten Fall, wenn Sie JavaScript verwenden, um eine Ressource aus einem anderen Ursprung zu erstellen, wird der Inhalt eines <script>, <link rel=stylesheet>, <img>, <video>, <audio>, <object>, <embed> Oder <iframe> (Was funktioniert, weil das Einbetten von Ressourcen über Ursprungsgrenzen hinweg erlaubt ist) - aber aus irgendeinem Grund tun Sie dies nicht Sie möchten oder können dies nicht, indem Sie die Ressourcen-URL als href- oder src-Attribut für das Element verwenden.

  • Wenn Sie eine Ressource nur zwischenspeichern möchten. Wie in der Antwort unter angedeutet, gelten für undurchsichtige Antworten folgende Einschränkungen:In der Praxis gilt das Szenario, in dem Sie sich befinden In diesem Fall ist die API, die relevant ist, die Cache-Speicher-API .

Aber auch in diesen wenigen Fällen sind einige wichtige Fallstricke zu beachten. Siehe die Antwort unter Welche Einschränkungen gelten für undurchsichtige Antworten?für die Details.


Ich habe auch versucht, das Objekt { mode: 'opaque'}

Es gibt keinen Anforderungsmodus mode: 'opaque' - opaque ist stattdessen nur eine Eigenschaft der Antwort , und Browser legen diese undurchsichtige Eigenschaft für Antworten auf gesendete Anforderungen fest mit dem Modus no-cors.

Im Übrigen ist das Wort opakein ziemlich explizites Signal für die Art der Antwort, die Sie erhalten: "opak" bedeutet, dass Sie sie nicht sehen können.

139
sideshowbarker

Eine sehr einfache Lösung (2 Minuten zur Konfiguration) ist die Verwendung von local-ssl-proxy package von npm.

Die Verwendung ist geradlinig:
1. Installieren Sie das Paket: npm install -g local-ssl-proxy
2. Während Sie Ihren local-server ausführen, maskieren Sie ihn mit dem local-ssl-proxy --source 9001 --target 9000

P.S: Ersetzen Sie --target 9000 durch den -- "number of your port" und --source 9001 durch --source "number of your port +1" 

0
volna

Die einfache Lösung: Fügen Sie Folgendes ganz oben in die PHP-Datei ein, von der Sie die Daten anfordern.

header("Access-Control-Allow-Origin: *");

0

Wenn Sie also wie ich eine Website auf localhost entwickeln, auf der Sie versuchen, Daten von der Laravel-API abzurufen und in Ihrem Vue -Front-End zu verwenden, wird dies angezeigt Problem, hier ist, wie ich es gelöst habe:

  1. Führen Sie in Ihrem Laravel Projekt den Befehl php artisan make:middleware Cors aus. Dadurch wird app/Http/Middleware/Cors.php für Sie erstellt.
  2. Fügen Sie den folgenden Code in die Funktion handles in Cors.php ein:

    return $next($request)
        ->header('Access-Control-Allow-Origin', '*')
        ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
    
  3. Fügen Sie in app/Http/kernel.php den folgenden Eintrag in das Array $routeMiddleware ein:

    ‘cors’ => \App\Http\Middleware\Cors::class
    

    (Es gibt andere Einträge im Array wie auth, guest usw. Stellen Sie auch sicher, dass Sie dies in app/Http/kernel.php tun, da es in Laravel auch einen anderen kernel.php gibt.)

  4. Fügen Sie diese Middleware bei der Routenregistrierung für alle Routen hinzu, auf die Sie Zugriff gewähren möchten.

    Route::group(['middleware' => 'cors'], function () {
        Route::get('getData', 'v1\[email protected]');
        Route::get('getData2', 'v1\[email protected]');
    });
    
  5. Stellen Sie im Vue Frontend sicher, dass Sie diese API in mounted() function und nicht in data() aufrufen. Stellen Sie außerdem sicher, dass Sie http:// oder https:// mit der URL in Ihrem fetch() -Aufruf verwenden.

Voller Dank an Pete Houston Blogartikel .

0
dotNET

Die Lösung für mich war, es einfach serverseitig zu machen

Ich habe die C # WebClient-Bibliothek verwendet, um die Daten abzurufen (in meinem Fall waren es Bilddaten) und sie an den Client zurückzusenden. In Ihrer gewählten serverseitigen Sprache gibt es wahrscheinlich etwas sehr ähnliches.

//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 Hauptpunkt ist, dass client.DownloadData() ohne CORS-Fehler gearbeitet hat. In der Regel gibt es CORS-Probleme nur zwischen Websites. Daher ist es in Ordnung, "standortübergreifende" Anforderungen von Ihrem Server aus zu stellen.

Dann ist der Aufruf zum Reagieren 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....
    )}
0
Stuart Aitken