Încercarea de a utiliza fetch și pass în modul: no-cors (Programare, Javascript, Reactjs, Cors, Creați Aplicația React, Fetch Api)

dwww a intrebat.

Pot să ating acest punct final, http://catfacts-api.appspot.com/api/facts?number=99 prin Postman și acesta returnează JSON

În plus, folosesc create-react-app și aș dori să evit configurarea oricărei configurații de server.

În codul meu de client încerc să folosesc fetch pentru a face același lucru, dar primesc eroarea:

Nici un antet „Access-Control-Allow-Origin” nu este prezent pe resursa solicitată. Origine ‘http://localhost:3000‘ nu are, prin urmare, acces permis. Dacă aveți nevoie de un răspuns opac, setați modul cererii la „no-cors” pentru a prelua resursa cu CORS dezactivat.

Așadar, încerc să trec un obiect în Fetch, care va dezactiva CORS, astfel:

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;
  });

Interesant este că eroarea pe care o primesc este de fapt o eroare de sintaxă cu această funcție. Nu sunt sigur că funcția mea reală fetch este stricată, deoarece atunci când elimin obiectul { mode: ‘no-cors’ } și îi furnizez o altă adresă URL, funcționează foarte bine.

Am încercat, de asemenea, să trec în obiect { mode: 'opaque'} , dar acest lucru returnează eroarea originală de mai sus.

Cred că tot ce trebuie să fac este să dezactivez CORS… Ce îmi scapă?

Comentarii

  • Răspunsul la întrebarea dvs. este acesta? Gestionați răspunsul – SyntaxError: Unexpected end of input when using mode: ‘no-cors’ –  > Por Cees Timmerman.
6 răspunsuri
sideshowbarker

mode: 'no-cors' nu va face ca prin magie lucrurile să funcționeze. De fapt, înrăutățește lucrurile, deoarece un efect pe care îl are este de a spune browserelor, „Blocați codul meu JavaScript din front-end să nu se uite la conținutul corpului și al antetului răspunsului în orice situație.” Bineînțeles că aproape niciodată nu doriți acest lucru.

Ceea ce se întâmplă cu solicitările cross-origin de la JavaScript frontend este că browserele blochează în mod implicit codul frontend de la accesarea resurselor cross-origin. Dacă Access-Control-Allow-Origin se află într-un răspuns, atunci browserele vor relaxa acest blocaj și vor permite codului dvs. să acceseze răspunsul.

Dar dacă un site nu trimite niciun Access-Control-Allow-Origin în răspunsurile sale, codul dvs. frontal nu poate accesa direct răspunsurile de pe acel site. În special, nu puteți rezolva acest lucru specificând mode: 'no-cors' (de fapt, acest lucru va asigura codul dvs. frontend nu poate accesa conținutul răspunsurilor).

Cu toate acestea, un lucru pe care va fi funcționează: dacă trimiteți cererea prin un proxy CORS.

De asemenea, vă puteți implementa cu ușurință propriul proxy în Heroku în doar 2-3 minute, cu 5 comenzi:

git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master

După ce executați aceste comenzi, veți avea propriul server CORS Anywhere care va rula, de exemplu, la adresa , https://cryptic-headland-94862.herokuapp.com/.

Prefixați URL-ul de cerere cu URL-ul proxy-ului dvs.; de exemplu:

https://cryptic-headland-94862.herokuapp.com/https://example.com

Adăugarea URL-ului proxy ca prefix face ca solicitarea să fie făcută prin intermediul proxy-ului dumneavoastră, care apoi:

  1. Redirecționează cererea către https://example.com.
  2. Primește răspunsul de la https://example.com.
  3. Adaugă Access-Control-Allow-Origin la răspuns.
  4. Transmite răspunsul, cu antetul adăugat, înapoi la codul frontend solicitant.

Browserul permite apoi codului frontal să acceseze răspunsul, deoarece acel răspuns cu antetul Access-Control-Allow-Origin header-ul de răspuns este ceea ce vede browserul.

Acest lucru funcționează chiar dacă solicitarea este una care determină browserele să efectueze o verificare prealabilă CORS. OPTIONS pentru că, în acest caz, proxy-ul trimite înapoi, de asemenea, antetul Access-Control-Allow-Headers și Access-Control-Allow-Methods necesare pentru ca verificarea preliminară să aibă succes.


Pot să accesez acest endpoint, http://catfacts-api.appspot.com/api/facts?number=99 prin Postman

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS explică de ce, chiar dacă puteți accesa răspunsul cu Postman, browserele nu vă permit să accesați răspunsul cross-origin din codul JavaScript frontend care rulează într-o aplicație web decât dacă răspunsul include un cod Access-Control-Allow-Origin antet de răspuns.

http://catfacts-api.appspot.com/api/facts?number=99 nu are Access-Control-Allow-Origin antet de răspuns, deci nu există nicio modalitate prin care codul frontend să poată accesa răspunsul cross-origin.

Browserul dvs. poate obține răspunsul fără probleme și îl puteți vedea în Postman și chiar în devtools pentru browsere – dar asta nu înseamnă că browserele îl vor expune codului dvs. Nu o vor face, pentru că nu are Access-Control-Allow-Origin antet de răspuns. Așa că trebuie să folosiți un proxy pentru a-l obține.

Proxy-ul face o cerere către acel site, primește răspunsul, adaugă antetul Access-Control-Allow-Origin antetul de răspuns și orice alt antet CORS necesar, apoi îl transmite înapoi codului dumneavoastră solicitant. Iar acel răspuns cu antetul Access-Control-Allow-Origin este ceea ce vede browserul, astfel încât browserul permite codului dvs. frontal să acceseze de fapt răspunsul.


Așadar, încerc să trec un obiect în Fetch, care va dezactiva CORS

Nu doriți să faceți asta. Pentru a fi clar, când spuneți că doriți să „dezactivați CORS”, se pare că de fapt vreți să spuneți că doriți să dezactivați politica de aceeași origine. CORS în sine este, de fapt, o modalitate de a face acest lucru – CORS este o modalitate de a relaxa politica de aceeași origine, nu o modalitate de a o restricționa.

Dar, oricum, este adevărat că puteți – doar în mediul dvs. local – să faceți lucruri cum ar fi să dați browserului dvs. stegulețe de execuție pentru a dezactiva securitatea și pentru a rula în condiții de nesiguranță sau puteți instala o extensie de browser la nivel local pentru a ocoli politica de același origine, dar tot ceea ce faceți este să schimbați situația doar pentru dvs. la nivel local.

Indiferent de ceea ce schimbați la nivel local, orice altă persoană care încearcă să utilizeze aplicația dvs. se va confrunta în continuare cu politica de aceeași origine și nu există nicio modalitate de a dezactiva acest lucru pentru alți utilizatori ai aplicației dvs.

Cel mai probabil nu veți dori niciodată să utilizați mode: 'no-cors' în practică, cu excepția câtorva cazuri limitate, , și chiar și atunci numai dacă știți exact ce faceți și care sunt efectele. Asta pentru că ceea ce setarea mode: 'no-cors' spune de fapt browserului este, „Blochează codul meu JavaScript din front-end să se uite în conținutul corpului răspunsului și al antetelor în orice situație”. În cele mai multe cazuri, este evident că nu este chiar ceea ce vă doriți.


În ceea ce privește cazurile în care ar trebui să doriți să luați în considerare utilizarea mode: 'no-cors', , consultați răspunsul de la Ce limitări se aplică răspunsurilor opace? pentru detalii. Esența este că cazurile sunt:

  • În cazul limitat în care folosiți JavaScript pentru a introduce conținut de la o altă origine într-un <script>, , <link rel=stylesheet>, , <img>, , <video>, , <audio>, , <object>, , <embed>, , sau <iframe> (ceea ce funcționează, deoarece încorporarea resurselor cross-origin este permisă pentru acestea) – dar dintr-un motiv oarecare, nu vreți sau nu puteți face acest lucru doar dacă marcajul documentului folosește URL-ul resursei ca element href sau src pentru element.

  • Atunci când singurul lucru pe care doriți să îl faceți cu o resursă este să o puneți în memoria cache. După cum se menționează în răspuns Ce limitări se aplică răspunsurilor opace?, , în practică, scenariul la care se aplică este atunci când folosiți Service Workers, caz în care API-ul relevant este API-ul Cache Storage API.

Dar chiar și în aceste cazuri limitate, există câteva gotchas importante de care trebuie să fii conștient; consultați răspunsul la Ce limitări se aplică răspunsurilor opace? pentru detalii.


Am încercat, de asemenea, să trec în obiectul { mode: 'opaque'}

Nu există nici un mode: 'opaque' mod de solicitare – opaque este în schimb doar o proprietate a obiectului răspuns, , iar browserele setează această proprietate opacă pe răspunsurile de la cererile trimise cu no-cors mod.

Dar, întâmplător, cuvântul opaque este un semnal destul de explicit cu privire la natura răspunsului pe care îl veți primi în final: „opac” înseamnă că nu îl puteți vedea.

Comentarii

  • Iubiți cors-anywhere soluția pentru cazuri simple de utilizare non-prod (de exemplu, preluarea unor date disponibile public). Acest răspuns îmi confirmă suspiciunea că no-cors nu este comună pentru că OpaqueResponse nu este foarte util; adică „cazuri foarte limitate”; poate cineva să-mi explice exemple în care no-cors este util? –  > Por Mazăre Roșu.
  • @TheRedPea Vedeți actualizarea pe care am făcut-o la răspuns aici (și pe care am adăugat-o și ca și comentarii pentru întrebarea dvs. la stackoverflow.com/questions/52569895/…) – –  > Por sideshowbarker.
  • Trebuia să îmi configurez serverul Express cu pachetul CORS.js – github.com/expressjs/cors – și apoi a trebuit să elimin mode: 'no-cors' din cererea de preluare (altfel răspunsul ar fi fost gol) –  > Por James L..
  • proxy-ul CORS este grozav. Sunt uimit de faptul că este considerată o măsură de „securitate” să blochezi deloc accesul la fișierele publice. Este atât de, atât de ușor de ocolit din perspectiva unui hacker, și exact asta face acest lucru. Este într-adevăr doar o bătaie de cap pentru actorii buni. –  > Por Seph Reed.
  • Generez codul unor clienți diferiți care consumă același API. Îl folosesc pentru traininguri. Vreau să păstrez codul simplu și să las utilizatorii să se joace cu el. Trebuie să folosesc no-cros. –  > Por profimedica.
dotNET

Așadar, dacă sunteți ca mine și dezvoltați un site web pe localhost în care încercați să preluați date de la API-ul Laravel și să le folosiți în front-end-ul Vue și vedeți această problemă, iată cum am rezolvat-o eu:

  1. În proiectul tău Laravel, execută comanda php artisan make:middleware Cors. Aceasta va crea app/Http/Middleware/Cors.php pentru tine.
  2. Adăugați următorul cod în interiorul fișierului handles în Cors.php:

    return $next($request)
        ->header('Access-Control-Allow-Origin', '*')
        ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
    
  3. În app/Http/kernel.php, , adăugați următoarea intrare în $routeMiddleware array:

    ‘cors’ => AppHttpMiddlewareCors::class
    

    (Ar mai fi și alte intrări în array, cum ar fi auth, , guest etc. De asemenea, asigurați-vă că faceți acest lucru în app/Http/kernel.php deoarece există un alt fișier kernel.php și în Laravel)

  4. Adăugați acest middleware la înregistrarea rutelor pentru toate rutele unde doriți să permiteți accesul, astfel:

    Route::group(['middleware' => 'cors'], function () {
        Route::get('getData', '[email protected]');
        Route::get('getData2', '[email protected]');
    });
    
  5. În Vue front-end, asigurați-vă că apelați acest API în mounted() și nu în funcția data(). De asemenea, asigurați-vă că folosiți http:// sau https:// cu URL-ul din fetch() apelul.

Credite complete pentru Pete Houston’s articolul de pe blogul lui Pete Houston.

Cod foarte frumos

Soluția simplă: Adăugați următoarele în partea de sus a fișierului php din care solicitați datele.

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

Comentarii

    27

  • Aceasta este o idee foarte bună dacă doriți să obțineți un nivel de securitate cât mai mic posibil :). –  > Por Maimuța eretică.
  • cum rămâne cu hotlink-ul pentru imagini –  > Por user889030.
  • O idee foarte bună, dacă controlezi sursa. –  > Por baash05.
Stuart Aitken

Soluția pentru mine a fost să o fac doar pe partea serverului

Am folosit C# WebClient pentru a obține datele (în cazul meu erau date de imagine) și a le trimite înapoi la client. Probabil că există ceva foarte asemănător în limbajul ales de tine pentru partea de server.

//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);
    }
}

Puteți să-l adaptați la orice caz de utilizare al dumneavoastră. Ideea principală este client.DownloadData() a funcționat fără nicio eroare CORS. În mod obișnuit, problemele CORS apar doar între site-uri web, de aceea este în regulă să faceți cereri „cross-site” de pe serverul dvs.

Apoi, apelul React fetch este la fel de simplu ca:

//React component

fetch(`api/ItemImage/GetItemImageFromURL?url=${imageURL}`, {            
        method: 'GET',
    })
    .then(resp => resp.json() as Promise<ItemImage>)
    .then(imgResponse => {

       // Do more stuff....
    )}

volna

O soluție foarte simplă (2 min de configurare) este să folosiți local-ssl-proxy din pachetul npm

Utilizarea este destul de directă:
1. Instalați pachetul:npm install -g local-ssl-proxy
2. În timp ce rulați aplicația dvs. local-server mascați-l cu opțiunea local-ssl-proxy --source 9001 --target 9000

P.S: Înlocuiți --target 9000 cu -- "number of your port" și --source 9001 cu --source "number of your port +1"

Comentarii

  • Am o problemă cu utilizarea aplicației mele pe un dispozitiv telefonic real. Este soluția dvs. utilă pentru acest caz? –  > Por Hamid Araghi.
  • @HamidAraghi Presupun că acum, din moment ce, în scopuri de dezvoltare, serverul proxy ar trebui să ruleze pe dispozitivul care este de fapt afectat de eroare –  > Por volna.
Varnit Rohilla

Dacă utilizați Express ca back-end, trebuie doar să instalați cors și să importați și să îl utilizați în app.use(cors());.Dacă nu se rezolvă, încercați să schimbați porturile.Se va rezolva cu siguranță după schimbarea porturilor