Kako odpraviti napake CORS (in zakaj nastanejo)
Napaka CORS pomeni, da je vaša spletna stran poskusila prebrati odgovor z drugega izvora (druge domene, vrat ali protokola), strežnik pa ni poslal glav, ki bi to dovolile. Brskalniki blokirajo odgovor, da zaščitijo uporabnike. Popravite jo na strežniku tako, da vrnete glavo Access-Control-Allow-Origin za izvor vašega spletnega mesta in obdelate predletne zahteve OPTIONS, ali se ji izognete tako, da zahtevo pošljete prek lastnega zaledja na istem izvoru.
Gre za eno najbolj zmedenih napak pri razvoju spleta, ker strežnik zahtevo pogosto prejme brez težav. Ta vodnik pojasni, kaj se dogaja, in kako popraviti vsako različico.
Kaj pomeni »izvor«
Izvor je kombinacija protokola, domene in vrat:
| URL | Izvor |
|---|---|
https://myapp.com/dashboard | https://myapp.com |
https://api.myapp.com/users | https://api.myapp.com (druga poddomena, zato drug izvor) |
http://localhost:5173 | http://localhost:5173 |
http://localhost:3000 | http://localhost:3000 (druga vrata, zato drug izvor) |
Brskalniki sledijo politiki istega izvora: JavaScript na strani lahko prosto bere odgovore s svojega izvora, z drugih pa ne. CORS (Cross-Origin Resource Sharing) je sistem, ki strežniku omogoča privolitev: »odgovore z mene lahko berejo strani z teh izvorov.«
Dve posledici presenetita ljudi:
- Zahteva pogosto doseže strežnik. CORS običajno blokira vašo kodo pri branju odgovora, ne strežnika pri prejemu zahteve. POST je lahko shranjen, čeprav ste videli napako.
- Samo brskalniki ga uveljavljajo. curl, Postman in koda na strežniku CORS popolnoma ignorirajo. Zato »v Postmanu deluje« ne pove ničesar o CORS.
1. korak: preberite točno napako
Odprite orodja za razvijalce (desni klik → Preglej), pojdite na Konzolo in preberite celotno sporočilo. Besedilo Chroma pove, katera težava je:
| Sporočilo vsebuje | Kaj ni v redu |
|---|---|
No 'Access-Control-Allow-Origin' header is present | Strežnik glave sploh ni poslal ali je zahteva odpovedala, preden je prišla do vaše kode CORS (na primer 404 ali 500) |
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied origin | Strežnik dovoljuje drug izvor, kot je vaš |
Response to preflight request doesn't pass access control check | Predletna zahteva OPTIONS ni uspela |
...must not be the wildcard '*' when the request's credentials mode is 'include' | Pošiljate piškotke, strežnik pa je odgovoril z * |
Request header field authorization is not allowed | Strežnik te glave ni naštel v Access-Control-Allow-Headers |
Nato odprite zavihek Omrežje, poiščite neuspešno zahtevo (in morebitno zahtevo OPTIONS pred njo) ter poglejte njeno statusno kodo in glave odgovora.
Najprej preverite statusno kodo. Številne »napake CORS« so v resnici napake strežnika v preoblačilu. Če strežnik zruši ali vrne 404, njegov odgovor o napaki pogosto nima glav CORS, zato brskalnik poroča o CORS namesto o pravi težavi. Popravite 500 ali 404, in napaka CORS morda izgine.
2. korak: odločite, ali naj brskalnik sploh kliče ta API
Preden dodate glave, vprašajte: ali naj brskalnik sploh kliče ta API?
- API tretje osebe, ki potrebuje skrivni ključ (OpenAI, skrivni ključ Stripe, večina storitev e-pošte) ne sme biti klican iz brskalnika. Ključ bi bil viden vsakemu obiskovalcu. Kličite ga iz svojega zaledja, napaka CORS pa izgine, ker zahteve med strežnikoma niso predmet CORS. Glejte kako varno hraniti API ključe.
- API tretje osebe, ki ga ne nadzirate in ne pošilja glav CORS, ne morete popraviti na svoji strani. Kličite ga iz svojega zaledja.
- Lasten API lahko popravite s pravilno nastavitvijo. Nadaljujte spodaj.
3. korak: popravite na strežniku
Strežnik mora dodati prave glave k svojim odgovorom, vključno z odgovori o napakah.
Za dejansko zahtevo pošljite:
Access-Control-Allow-Origin: https://myapp.com(točen izvor vašega frontenda, brez končne poševnice)Vary: Origin, če se vrednost spreminja glede na to, kateri izvor je vprašal
Za predletno zahtevo OPTIONS odgovorite z uspešno statusno kodo (200 ali 204) in:
Access-Control-Allow-Origin: https://myapp.comAccess-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETEAccess-Control-Allow-Headers: Content-Type, Authorization(vsaka lastna glava, ki jo pošiljate)- Neobvezno
Access-Control-Max-Age: 600, da brskalnik predlet nekaj časa shrani v predpomnilnik
Večina ogrodij ima paket ali nastavitev, ki to naredi. V Expressu paket cors; v FastAPI CORSMiddleware; v ASP.NET Core AddCors; v Springu @CrossOrigin ali konfiguracija CORS. Tipična nastavitev v Expressu:
import cors from "cors";
app.use(cors({
origin: ["https://myapp.com", "http://localhost:5173"],
credentials: true,
}));
Obdelavo CORS postavite pred svoje poti in avtentikacijo, da predletne zahteve (ki nimajo prijave) ne zavrne 401.
Pri orodju za gradnjo z AI natančno opišite nastavitev:
Frontend na
https://myapp.comkliče API nahttps://api.myapp.comin dobi »Response to preflight request doesn't pass access control check«. Nastavi CORS na API-ju, da dovoli točnohttps://myapp.comin izvor predogleda, dovoli GET, POST, PATCH, DELETE z glavama Content-Type in Authorization, obdelaj OPTIONS pred avtentikacijo in vključi glave CORS tudi v odgovore o napakah.
4. korak: obravnavajte piškotke in poverilnice
Če frontend pošilja piškotke (na primer sejo za prijavo) drugemu izvoru, se morata obe strani strinjati:
- Frontend nastavi
credentials: "include"prifetchaliwithCredentials: truepri axios. - Strežnik pošlje
Access-Control-Allow-Credentials: true. - Strežnikova
Access-Control-Allow-Originmora biti točen izvor, ne*.
Piškotki med spletnimi mesti potrebujejo tudi SameSite=None; Secure, nekateri brskalniki pa tretjeosebne piškotke dodatno omejujejo. To je še en razlog, da raje izberete pristop iz 5. koraka.
5. korak: izogibajte se CORS z nastavitvijo istega izvora
Pogosto je najčistejša rešitev, da sploh ne pošiljate zahtev med izvori. Strezite API z istega izvora kot stran, na primer na https://myapp.com/api/...:
- V razvoju lahko večina razvojnih strežnikov deluje kot posrednik. Nastavitev
server.proxyv Vite lahko posreduje/apivašemu zaledju na drugih vratih, tako da brskalnik komunicira samo z enim izvorom. - V produkciji usmerite
/apina zaledje z nastavitvami prepisovanja ali posredovanja vašega gostitelja, ali streženje frontenda in API-ja z enega strežnika.
Frontend nato kliče relativno pot, na primer fetch("/api/orders"). Ni zahteve med izvori, ni predleta med izvori in ni težav s piškotki. Prav tako vam ni treba trdo kodirati domene API-ja, ki se razlikuje med predogledom in produkcijo.
Spremeni frontend, da kliče zaledje z relativnimi potmi /api namesto polnega URL-ja, in nastavi razvojni posrednik, ki /api posreduje strežniku API. Nato odstrani nastavitve CORS, ki jih ne potrebujemo več.
Česa ne storiti
mode: "no-cors"vfetch. Ničesar ne zaobide; vaši kodi da prazen, nepregleden odgovor.- Razširitve brskalnika, ki izklopijo CORS. Spremenijo samo vaš brskalnik. Vsak obiskovalec še vedno vidi napako.
- Javne storitve »CORS proxy« za prave aplikacije. Lahko preberejo in spremenijo vse, kar gre skozi njih, in ne delujejo vedno.
Access-Control-Allow-Origin: *pri API-ju, ki uporablja prijave. Tako ali tako ne deluje s poverilnicami in je napačna privzeta nastavitev za zasebne podatke.- Odsevanje poljubne glave
Originnazaj z dovoljenimi poverilnicami. Tako lahko katerakoli spletna stran pošilja zahteve v imenu prijavljenih uporabnikov. Uporabite seznam dovoljenih.
Pogosti vzroki v aplikacijah, zgrajenih z AI
| Situacija | Popravek |
|---|---|
| Frontend kliče API tretje osebe s skrivnim ključem | Premaknite klic na zaledje |
| Deluje v predogledu, ne deluje na objavljeni domeni | Dodajte objavljeni izvor in izvor domene po meri na seznam dovoljenih ali uporabite relativne poti /api |
| Napaka se pojavi samo pri POST, PUT ali DELETE | Predletna zahteva ni obdelana; dodajte obdelavo OPTIONS in dovoljene glave |
| Napaka se je pojavila po dodajanju prijave | Poverilnice zahtevajo točen izvor in Allow-Credentials |
| »Napaka CORS«, vendar zavihek Omrežje kaže 500 | Najprej popravite napako strežnika |
URL API-ja trdo kodiran na localhost | Uporabite relativne poti ali nastavitev za posamezno okolje |
CORS v Mythex
Kadar ima projekt Mythex spletno mesto in strežnik API, oba tečeta kot storitvi v istem projektu, med njima pa lahko preklapljate v predogledu. Če agentu naročite, naj frontend kliče zaledje prek relativne poti /api, posredovane v razvoju, se izognete večini težav s CORS. Če res potrebujete klice med izvori, agentu dajte točno napako iz konzole in vpletene izvore. Preverite rezultat tudi v objavljeni aplikaciji, saj se njen naslov razlikuje od predogleda. Glejte Storitve z več deli in API zaledja v dokumentaciji ter naša vodnika o odpravljanju napak v aplikaciji, zgrajeni z AI in frontend proti zaledju.
Kontrolni seznam za CORS
- Prebrana celotna napaka v konzoli in statusna koda neuspele zahteve
- Izključen skrit 404 ali 500
- API-ji s skrivnimi ključi kličejo iz zaledja, ne iz brskalnika
- Strežnik pošilja
Access-Control-Allow-Origins točnimi dovoljenimi izvori - Predletna zahteva
OPTIONSodgovorjena z dovoljenimi metodami in glavami, pred avtentikacijo - Glave CORS prisotne tudi v odgovorih o napakah
- Poverilnice: točen izvor,
Allow-Credentials: true, pravilne nastavitve piškotkov - Predogled, objavljen izvor in izvor domene po meri so vsi zajeti ali pa se uporabljajo relativne poti
/api - Brez
no-cors, javnih posrednikov ali bližnjic z odsevanjem poljubnega izvora
Vprašanja
Kaj pomeni napaka CORS?
Vaša stran, naložena iz enega izvora, je poskusila prebrati odgovor z drugega izvora, strežnik tega odgovora pa ni vključil glav, ki bi to dovolile. Brskalnik blokira vašo kodo, da odgovora ne more prebrati. Popravek je na strežniku ali v tem, kako je zahteva usmerjena, ne v kodi frontenda.
Ali lahko napako CORS popravim na frontendu?
Ne na pravi način. Nastavitve kot mode: 'no-cors' samo skrijejo odgovor pred vašo kodo. Popravite jo tako, da strežnik pošlje pravilno glavo Access-Control-Allow-Origin, ali tako, da API kličete iz lastnega zaledja ali posredniškega strežnika istega izvora.
Ali je Access-Control-Allow-Origin: * varno?
Ustrezno je za javne podatke, ki jih lahko kdorkoli bere, na primer javni API brez prijave. Ne more se uporabljati s piškotki ali drugimi poverilnicami, za zasebne API-je pa morate navesti točne dovoljene izvore.
Zakaj zahteva deluje v Postmanu ali curl, v brskalniku pa ne?
CORS uveljavljajo samo brskalniki. Orodja kot Postman in curl ga ne uporabljajo, zato zahteva lahko uspe tam in vseeno ostane blokirana, ko jo pošlje JavaScript na strani.
Kaj je predletna zahteva (preflight)?
Pri zahtevah, ki niso preproste, kot je POST s JSON ali zahteva z glavo Authorization, brskalnik najprej pošlje zahtevo OPTIONS in vpraša strežnik, katere metode in glave so dovoljene. Če zahteva OPTIONS ne uspe ali nima pravilnih glav, prava zahteva sploh ni poslana.