Kako popraviti CORS greške (i zašto nastaju)
CORS greška znači da je vaša web stranica pokušala pročitati odgovor s drugog izvora (druge domene, porta ili protokola), a taj poslužitelj nije poslao zaglavlja koja kažu da je to dopušteno. Preglednici blokiraju odgovor radi zaštite korisnika. Popravljate to na poslužitelju tako da vraća zaglavlje Access-Control-Allow-Origin za izvor vaše stranice i obrađuje OPTIONS preflight zahtjeve, ili to zaobiđete slanjem zahtjeva kroz vlastiti back-end na istom izvoru.
Među najzbunjujućim greškama u web razvoju je ova, jer zahtjev često uredno stigne do poslužitelja. Ovaj vodič objašnjava što se događa i kako popraviti svaku varijantu.
Što znači „izvor”
Izvor je kombinacija protokola, domene i porta:
| URL | Izvor |
|---|---|
https://myapp.com/dashboard | https://myapp.com |
https://api.myapp.com/users | https://api.myapp.com (drugačija poddomena, pa drugačiji izvor) |
http://localhost:5173 | http://localhost:5173 |
http://localhost:3000 | http://localhost:3000 (drugačiji port, pa drugačiji izvor) |
Preglednici slijede politiku istog izvora: JavaScript na stranici može slobodno čitati odgovore sa svog izvora, ali ne i s drugih. CORS (Cross-Origin Resource Sharing) je sustav kojim poslužitelj daje dopuštenje: „odgovore od mene mogu čitati stranice s ovih izvora”.
Dvije posljedice iznenade ljude:
- Zahtjev često stigne do poslužitelja. CORS obično blokira vaš kod da pročita odgovor, a ne poslužitelj da primi zahtjev. POST je možda spremljen iako ste vidjeli grešku.
- Samo preglednici ga primjenjuju. curl, Postman i kod na poslužitelju ignoriraju CORS. Zato „radi u Postmanu” ne govori ništa o CORS-u.
Korak 1: Pročitajte točnu grešku
Otvorite alate za razvojne programere (desni klik → Inspect), idite na Console i pročitajte cijelu poruku. Chromeova formulacija pokazuje koji problem imate:
| Poruka sadrži | Što nije u redu |
|---|---|
No 'Access-Control-Allow-Origin' header is present | Poslužitelj uopće nije poslao zaglavlje ili je zahtjev pao prije nego što je došao do vašeg CORS koda (npr. 404 ili 500) |
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied origin | Poslužitelj dopušta drugi izvor nego vaš |
Response to preflight request doesn't pass access control check | OPTIONS preflight nije prošao |
...must not be the wildcard '*' when the request's credentials mode is 'include' | Šaljete kolačiće, a poslužitelj je odgovorio s * |
Request header field authorization is not allowed | Poslužitelj nije naveo to zaglavlje u Access-Control-Allow-Headers |
Zatim otvorite karticu Network, pronađite zahtjev koji ne prolazi (i sve OPTIONS zahtjeve prije njega) te pogledajte statusni kod i zaglavlja odgovora.
Prvo provjerite statusni kod. Mnoge „CORS greške” zapravo su greška poslužitelja u prerušenju. Ako poslužitelj padne ili vrati 404, njegov odgovor često nema CORS zaglavlja, pa preglednik prijavi CORS umjesto pravog problema. Popravite 500 ili 404 i CORS greška može nestati.
Korak 2: Odlučite treba li preglednik uopće zvati taj API
Prije dodavanja zaglavlja pitajte se: treba li preglednik izravno zvati ovaj API?
- API treće strane koji traži tajni ključ (OpenAI, Stripe tajni ključ, većina servisa za e-poštu) nikad se ne smije zvati iz preglednika. Ključ bi bio vidljiv svakom posjetitelju. Zovite ga iz svog back-enda i CORS problem nestaje, jer zahtjevi od poslužitelja do poslužitelja ne podliježu CORS-u. Pogledajte kako čuvati API ključeve.
- API treće strane koji ne kontrolirate i ne šalje CORS zaglavlja ne možete popraviti sa svoje strane. Zovite ga iz svog back-enda.
- Vaš API možete popraviti pravilnom konfiguracijom. Nastavite dolje.
Korak 3: Popravite na svom poslužitelju
Poslužitelj mora dodavati ispravna zaglavlja svojim odgovorima, uključujući odgovore s greškom.
Za stvarni zahtjev pošaljite:
Access-Control-Allow-Origin: https://myapp.com(točan izvor vašeg front-enda, bez završne kose crte)Vary: Origin, ako vrijednost ovisi o tome koji je izvor pitao
Za preflight OPTIONS zahtjev odgovorite uspješnim statusom (200 ili 204) i:
Access-Control-Allow-Origin: https://myapp.comAccess-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETEAccess-Control-Allow-Headers: Content-Type, Authorization(svako prilagođeno zaglavlje koje šaljete)- Opcionalno
Access-Control-Max-Age: 600, da preglednik predmemorira preflight neko vrijeme
Većina okvira ima paket ili postavku koja to radi. U Expressu je to paket cors; u FastAPI-ju CORSMiddleware; u ASP.NET Core AddCors; u Springu @CrossOrigin ili konfiguracija CORS-a. Tipična postavka u Expressu:
import cors from "cors";
app.use(cors({
origin: ["https://myapp.com", "http://localhost:5173"],
credentials: true,
}));
Stavite CORS obradu prije svojih ruta i autentifikacije, da preflight zahtjevi (koji nemaju prijavu) ne budu odbijeni s 401.
S AI graditeljem opišite postavku precizno:
Front-end na
https://myapp.comzove API nahttps://api.myapp.comi dobiva „Response to preflight request doesn't pass access control check”. Konfiguriraj CORS na API-ju da dopušta točnohttps://myapp.comi izvor pregleda, dopusti GET, POST, PATCH, DELETE s Content-Type i Authorization zaglavljima, obradi OPTIONS prije autentifikacije i uključi CORS zaglavlja i u odgovore s greškom.
Korak 4: Obradite kolačiće i kredencijale
Ako vaš front-end šalje kolačiće (npr. sesiju prijave) na drugi izvor, obje strane se moraju složiti:
- Front-end postavlja
credentials: "include"ufetch, iliwithCredentials: trueu axiosu. - Poslužitelj šalje
Access-Control-Allow-Credentials: true. - Poslužiteljev
Access-Control-Allow-Originmora biti točan izvor, a ne*.
Kolačići između stranica također trebaju SameSite=None; Secure, a neki preglednici dodatno ograničavaju kolačiće trećih strana. To je još jedan razlog da preferirate pristup iz Koraka 5.
Korak 5: Izbjegnite CORS postavkom istog izvora
Često je najčišće rješenje ne praviti zahtjeve između izvora uopće. Poslužujte API s istog izvora kao stranicu, npr. na https://myapp.com/api/...:
- U razvoju većina razvojnih servera može proksirati. Vite postavka
server.proxymože prosljeđivati/apina vaš back-end na drugom portu, pa preglednik uvijek razgovara samo s jednim izvorom. - U produkciji usmjerite
/apina back-end kroz postavke rewritea ili proxyja vašeg hosta, ili poslužite front-end i API s jednog poslužitelja.
Front-end tada zove relativnu putanju poput fetch("/api/orders"). Nema zahtjeva između izvora, nema preflighta između izvora i nema problema s kolačićima. Također ne morate hardkodirati domenu API-ja koja se razlikuje između pregleda i produkcije.
Promijeni front-end da zove back-end relativnim /api putanjama umjesto punog URL-a i postavi razvojni proxy da /api prosljeđuje API serveru. Zatim ukloni CORS postavke koje više ne trebamo.
Što ne raditi
mode: "no-cors"ufetch. Ništa ne zaobilazi; vašem kodu daje prazan, nečitljiv odgovor.- Dodaci za preglednik koji isključuju CORS. Mijenjaju samo vaš preglednik. Svaki posjetitelj i dalje vidi grešku.
- Javne „CORS proxy” usluge za prave aplikacije. Mogu čitati i mijenjati sve što prolazi kroz njih, a i padaju.
Access-Control-Allow-Origin: *na API-ju koji koristi prijave. Ne radi s kredencijalima i pogrešan je zadani izbor za privatne podatke.- Vraćanje bilo kojeg
Originzaglavlja natrag uz dopuštene kredencijale. To omogućuje bilo kojoj web stranici da šalje zahtjeve u ime vaših prijavljenih korisnika. Koristite popis dopuštenih.
Uobičajeni uzroci u aplikacijama izgrađenim uz AI
| Situacija | Popravak |
|---|---|
| Front-end zove API treće strane s tajnim ključem | Premjestite poziv na back-end |
| Radi u pregledu, ne radi na objavljenoj domeni | Dodajte objavljeni izvor i izvor prilagođene domene na popis dopuštenih ili koristite relativne /api putanje |
| Greška samo kod POST, PUT ili DELETE | Preflight nije obrađen; dodajte obradu OPTIONS i dopuštena zaglavlja |
| Greška se pojavila nakon dodavanja prijave | Kredencijali traže točan izvor i Allow-Credentials |
| „CORS greška”, ali Network kartica pokazuje 500 | Prvo popravite grešku poslužitelja |
URL API-ja hardkodiran na localhost | Koristite relativne putanje ili postavku po okruženju |
CORS u Mythexu
Kad Mythex projekt ima web stranicu i API poslužitelj, oboje rade kao servisi u istom projektu i možete se prebacivati između njih u pregledu. Ako zamolite agenta da front-end zove back-end kroz relativnu /api putanju, proksiranu u razvoju, izbjegavate većinu CORS problema. Ako ipak trebate pozive između izvora, dajte agentu točnu grešku iz konzole i uključene izvore. Provjerite rezultat i na objavljenoj aplikaciji, jer se njezina adresa razlikuje od pregleda. Pogledajte Aplikacije s više servisa i API backendi u dokumentaciji te naše vodiče o otklanjanju grešaka u aplikaciji izgrađenoj uz AI i frontend naspram backenda.
Popis za CORS
- Pročitana cijela greška u konzoli i statusni kod neuspjelog zahtjeva
- Isključen skriveni 404 ili 500
- API-ji s tajnim ključevima zovu se iz back-enda, ne iz preglednika
- Poslužitelj šalje
Access-Control-Allow-Origins točnim dopuštenim izvorima -
OPTIONSpreflight odgovoren dopuštenim metodama i zaglavljima, prije autentifikacije - CORS zaglavlja prisutna i u odgovorima s greškom
- Kredencijali: točan izvor,
Allow-Credentials: true, ispravne postavke kolačića - Pregled, objavljena domena i prilagođena domena pokriveni ili su korištene relativne
/apiputanje - Bez
no-cors, javnih proxyja i rješenja koja vraćaju bilo koji izvor
Pitanja
Što znači CORS greška?
Vaša stranica, učitana s jednog izvora, pokušala je pročitati odgovor s drugog izvora, a odgovor tog poslužitelja nije sadržavao zaglavlja koja to dopuštaju. Preglednik blokira vašem kodu čitanje odgovora. Popravak je na poslužitelju ili u načinu usmjeravanja zahtjeva, ne u kodu front-enda.
Mogu li popraviti CORS grešku s frontenda?
Ne na pravi način. Postavke poput mode: 'no-cors' samo sakriju odgovor od vašeg koda. Popravljate tako da poslužitelj šalje ispravno zaglavlje Access-Control-Allow-Origin ili tako da API zovete s vlastitog back-enda ili proxyja na istom izvoru.
Je li Access-Control-Allow-Origin: * sigurno?
U redu je za javne podatke koje svatko smije čitati, poput javnog API-ja bez prijave. Ne može se koristiti s kolačićima ili drugim kredencijalima, a za privatne API-je trebate navesti točne dopuštene izvore.
Zašto zahtjev radi u Postmanu ili curlu, ali ne u pregledniku?
CORS primjenjuju samo preglednici. Alati poput Postmana i curla ga ne primjenjuju, pa zahtjev može uspjeti tamo, a ipak biti blokiran kad ga pošalje JavaScript stranice.
Što je preflight zahtjev?
Za zahtjeve koji nisu jednostavni, poput JSON POST zahtjeva ili zahtjeva s Authorization zaglavljem, preglednik prvo šalje OPTIONS zahtjev i pita poslužitelj koje metode i zaglavlja su dopuštene. Ako taj OPTIONS zahtjev ne uspije ili nema ispravna zaglavlja, pravi zahtjev se nikad ne šalje.