Vodiči

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:

URLIzvor
https://myapp.com/dashboardhttps://myapp.com
https://api.myapp.com/usershttps://api.myapp.com (drugačija poddomena, pa drugačiji izvor)
http://localhost:5173http://localhost:5173
http://localhost:3000http://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 presentPosluž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 originPoslužitelj dopušta drugi izvor nego vaš
Response to preflight request doesn't pass access control checkOPTIONS 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 allowedPosluž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.com
  • Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE
  • Access-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.com zove API na https://api.myapp.com i dobiva „Response to preflight request doesn't pass access control check”. Konfiguriraj CORS na API-ju da dopušta točno https://myapp.com i 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" u fetch, ili withCredentials: true u axiosu.
  • Poslužitelj šalje Access-Control-Allow-Credentials: true.
  • Poslužiteljev Access-Control-Allow-Origin mora 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.proxy može prosljeđivati /api na vaš back-end na drugom portu, pa preglednik uvijek razgovara samo s jednim izvorom.
  • U produkciji usmjerite /api na 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" u fetch. 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 Origin zaglavlja 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

SituacijaPopravak
Front-end zove API treće strane s tajnim ključemPremjestite poziv na back-end
Radi u pregledu, ne radi na objavljenoj domeniDodajte objavljeni izvor i izvor prilagođene domene na popis dopuštenih ili koristite relativne /api putanje
Greška samo kod POST, PUT ili DELETEPreflight nije obrađen; dodajte obradu OPTIONS i dopuštena zaglavlja
Greška se pojavila nakon dodavanja prijaveKredencijali traže točan izvor i Allow-Credentials
„CORS greška”, ali Network kartica pokazuje 500Prvo popravite grešku poslužitelja
URL API-ja hardkodiran na localhostKoristite 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-Origin s točnim dopuštenim izvorima
  • OPTIONS preflight 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 /api putanje
  • 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.

Mythex · Pricing · Izradite bilo što uz AI · Predlošci za web stranice i aplikacije · Mythex u usporedbi · Rječnik izrade aplikacija uz AI · Besplatni alati za izradu aplikacija uz AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)