Vodiči

Kako popraviti CORS greške (i zašto se javljaju)

CORS greška znači da je vaša web stranica pokušala da pročita odgovor sa drugog izvora (drugog domena, porta ili protokola), a taj server nije poslao zaglavlja koja kažu da je to dozvoljeno. Pregledači blokiraju odgovor radi zaštite korisnika. Popravljate je na serveru, tako što vraćate zaglavlje Access-Control-Allow-Origin za izvor vašeg sajta i obrađujete OPTIONS preflight zahteve, ili je izbegavate tako što zahtev šaljete preko sopstvenog back end-a na istom izvoru.

To je jedna od najzbunjujućih grešaka u web razvoju, jer zahtev često stiže do servera bez problema. Ovaj vodič objašnjava šta se dešava i kako popraviti svaku varijantu.

Šta znači „izvor“

Izvor je kombinacija protokola, domena i porta:

URLIzvor
https://myapp.com/dashboardhttps://myapp.com
https://api.myapp.com/usershttps://api.myapp.com (drugi poddomen, pa drugi izvor)
http://localhost:5173http://localhost:5173
http://localhost:3000http://localhost:3000 (drugi port, pa drugi izvor)

Pregledači poštuju politiku istog izvora: JavaScript na stranici može slobodno da čita odgovore sa sopstvenog izvora, ali ne i sa drugih. CORS (Cross-Origin Resource Sharing) je sistem kojim server daje saglasnost: „odgovore sa mene mogu da čitaju stranice sa ovih izvora.“

Dve stvari iznenade ljude:

  • Zahtev često stiže do servera. CORS obično blokira vaš kod da pročita odgovor, a ne da server primi zahtev. POST je možda sačuvan iako ste videli grešku.
  • Samo pregledači ga primenjuju. curl, Postman i kod na serveru ga potpuno ignorišu. Zato „radi u Postman-u“ ne govori ništa o CORS-u.

Korak 1: Pročitajte tačnu grešku

Otvorite alate za programere (desni klik → Inspect), idite na Console i pročitajte celu poruku. Chrome-ov tekst pokazuje koji problem imate:

Poruka sadržiŠta nije u redu
No 'Access-Control-Allow-Origin' header is presentServer uopšte nije poslao zaglavlje, ili je zahtev pukao pre nego što je stigao do vašeg CORS koda (na primer 404 ili 500)
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied originServer dozvoljava drugi izvor od vašeg
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 server je odgovorio sa *
Request header field authorization is not allowedServer nije naveo to zaglavlje u Access-Control-Allow-Headers

Zatim otvorite karticu Network, nađite neuspeli zahtev (i sve OPTIONS zahteve pre njega), i pogledajte njegov statusni kod i zaglavlja odgovora.

Prvo proverite statusni kod. Mnoge „CORS greške“ su zapravo serverska greška u maski. Ako server pukne ili vrati 404, njegov odgovor o grešci često nema CORS zaglavlja, pa pregledač prijavljuje CORS umesto pravog problema. Popravite 500 ili 404, a CORS greška može da nestane.

Korak 2: Odlučite da li uopšte treba da zovete taj API iz pregledača

Pre nego što dodate zaglavlja, pitajte se: treba li pregledač uopšte da zove ovaj API direktno?

  • API treće strane koji traži tajni ključ (OpenAI, Stripe tajni ključ, većina servisa za mejl) nikada ne treba zvati iz pregledača. Ključ bi bio vidljiv svakom posetiocu. Pozovite ga iz back end-a, a CORS problem nestaje, jer zahtevi između servera nisu predmet CORS-a. Pogledajte kako čuvati API ključeve bezbednim.
  • API treće strane koji ne kontrolišete i koji ne šalje CORS zaglavlja ne može se popraviti sa vaše strane. Pozovite ga iz back end-a.
  • Vaš API može da se popravi pravilnim podešavanjem. Nastavite dole.

Korak 3: Popravite na serveru

Server mora da dodaje ispravna zaglavlja svojim odgovorima, uključujući odgovore o greškama.

Za sam zahtev pošaljite:

  • Access-Control-Allow-Origin: https://myapp.com (tačan izvor vašeg frontenda, bez kose crte na kraju)
  • Vary: Origin, ako vrednost zavisi od toga koji izvor je pitao

Za preflight OPTIONS zahtev odgovorite statusom uspeha (200 ili 204) i sa:

  • 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)
  • Opciono Access-Control-Max-Age: 600, kako bi pregledač keširao preflight neko vreme

Većina framework-a ima paket ili podešavanje koje ovo radi. U Express-u je to paket cors; u FastAPI-ju CORSMiddleware; u ASP.NET Core-u AddCors; u Spring-u @CrossOrigin ili CORS konfiguracija. Tipično podešavanje u Express-u:

import cors from "cors";

app.use(cors({
  origin: ["https://myapp.com", "http://localhost:5173"],
  credentials: true,
}));

Stavite CORS obradu pre svojih ruta i autentifikacije, kako preflight zahtevi (koji nemaju prijavu) ne bi bili odbijeni sa 401.

Sa AI alatom za izradu, precizno opišite podešavanje:

Frontend na https://myapp.com poziva API na https://api.myapp.com i dobija „Response to preflight request doesn't pass access control check“. Podesi CORS na API-ju da dozvoli tačno https://myapp.com i izvor preview-a, dozvoli GET, POST, PATCH, DELETE sa zaglavljima Content-Type i Authorization, obradi OPTIONS pre autentifikacije, i uključi CORS zaglavlja i u odgovore o greškama.

Korak 4: Rukujte kolačićima i kredencijalima

Ako frontend šalje kolačiće (na primer sesiju za prijavu) ka drugom izvoru, obe strane moraju da se slože:

  • Frontend postavlja credentials: "include" na fetch, ili withCredentials: true u axios-u.
  • Server šalje Access-Control-Allow-Credentials: true.
  • Access-Control-Allow-Origin na serveru mora biti tačan izvor, a ne *.

Kolačići među sajtovima takođe zahtevaju SameSite=None; Secure na kolačiću, a neki pregledači dodatno ograničavaju kolačiće trećih strana. To je još jedan razlog da se preferira pristup iz Koraka 5.

Korak 5: Izbegnite CORS podešavanjem istog izvora

Često je najčistija popravka da uopšte ne pravite zahteve između izvora. Servirajte API sa istog izvora kao stranica, na primer na https://myapp.com/api/...:

  • U razvoju većina razvojnih servera može da radi kao proxy. Vite-ova podešavanja server.proxy mogu da prosleđuju /api na vaš back end na drugom portu, pa pregledač uvek razgovara sa samo jednim izvorom.
  • U produkciji rutirajte /api na back end kroz rewrite ili proxy podešavanja vašeg hosta, ili servirajte frontend i API sa jednog servera.

Frontend tada poziva relativnu putanju poput fetch("/api/orders"). Nema zahteva između izvora, nema preflight-a između izvora i nema problema sa kolačićima. Takođe znači da ne morate da ugrađujete domen API-ja koji se razlikuje između preview-a i produkcije.

Promeni frontend da poziva back end preko relativnih /api putanja umesto punog URL-a, i postavi razvojni proxy tako da /api ide na API server. Zatim ukloni CORS podešavanja koja više nisu potrebna.

Šta ne raditi

  • mode: "no-cors" u fetch-u. Ne zaobilazi ništa; vašem kodu daje prazan, nečitljiv odgovor.
  • Ekstenzije pregledača koje isključuju CORS. Menjaju samo vaš pregledač. Svaki posetilac i dalje vidi grešku.
  • Javni „CORS proxy“ servisi za prave aplikacije. Mogu da čitaju i menjaju sve što prolazi kroz njih, a i sami povremeno padaju.
  • Access-Control-Allow-Origin: * na API-ju koji koristi prijave. Ne radi sa kredencijalima, a loš je podrazumevani izbor za privatne podatke.
  • Vraćanje bilo kog Origin zaglavlja nazad uz dozvoljene kredencijale. Tako bilo koji sajt može da pravi zahteve u ime vaših korisnika koji su prijavljeni. Koristite listu dozvoljenih.

Česti uzroci u aplikacijama napravljenim uz AI

SituacijaPopravka
Frontend poziva API treće strane sa tajnim ključemPremestite poziv na back end
Radi u pregledu, ne radi na objavljenom domenuDodajte objavljeni i prilagođeni domen na listu dozvoljenih, ili koristite relativne /api putanje
Greška samo na POST, PUT ili DELETEPreflight nije obrađen; dodajte OPTIONS obradu i dozvoljena zaglavlja
Greška se pojavila posle dodavanja prijaveKredencijalima treba tačan izvor i Allow-Credentials
„CORS greška“, ali kartica Network pokazuje 500Prvo popravite serversku grešku
URL API-ja tvrdo kodiran na localhostKoristite relativne putanje ili podešavanje po okruženju

CORS u Mythex-u

Kada Mythex projekat ima sajt i API server, oba rade kao servisi u istom projektu, a između njih možete da prelazite u pregledu. Ako zamolite agenta da frontend zove back end preko relativne /api putanje, proksirane u razvoju, izbegavate većinu CORS problema. Ako vam ipak trebaju pozivi između izvora, dajte agentu tačnu grešku iz konzole i uključene izvore. Proverite rezultat i na objavljenoj aplikaciji, jer se njena adresa razlikuje od preview-a. Pogledajte Višeservisne aplikacije i API backend-i u dokumentaciji, i naše vodiče o otklanjanju grešaka u aplikaciji napravljenoj uz AI i frontend naspram backend-a.

Kontrolna lista za CORS

  • Pročitana cela greška u konzoli i statusni kod neuspelog zahteva
  • Isključen skriveni 404 ili 500
  • API-ji sa tajnim ključevima pozivaju se iz back end-a, a ne iz pregledača
  • Server šalje Access-Control-Allow-Origin sa tačnim dozvoljenim izvorima
  • OPTIONS preflight odgovara dozvoljenim metodama i zaglavljima, pre autentifikacije
  • CORS zaglavlja su prisutna i u odgovorima o greškama
  • Kredencijali: tačan izvor, Allow-Credentials: true, ispravna podešavanja kolačića
  • Izvori preview-a, objavljenog i prilagođenog domena pokriveni, ili su korišćene relativne /api putanje
  • Nema no-cors, javnih proxy-ja, ni prihvatanja bilo kog izvora

Pitanja

Šta znači CORS greška?

Vaša stranica, učitana sa jednog izvora, pokušala je da pročita odgovor sa drugog izvora, a odgovor tog servera nije sadržao zaglavlja koja to dozvoljavaju. Pregledač blokira vaš kod da pročita odgovor. Popravka je na serveru, ili u tome kako se zahtev rutira, a ne u frontend kodu.

Mogu li da popravim CORS grešku iz frontenda?

Ne na pravi način. Podešavanja poput mode: 'no-cors' samo sakrivaju odgovor od vašeg koda. Popravljate tako što server šalje ispravno zaglavlje Access-Control-Allow-Origin, ili tako što API pozivate iz sopstvenog back end-a ili proxy-ja na istom izvoru.

Da li je Access-Control-Allow-Origin: * bezbedno?

Dobro je za javne podatke koje svako sme da čita, poput javnog API-ja bez prijave. Ne može se koristiti sa kolačićima ili drugim kredencijalima, a za privatne API-je treba navesti tačne dozvoljene izvore.

Zašto zahtev radi u Postman-u ili curl-u, a ne u pregledaču?

CORS primenjuju samo pregledači. Alati poput Postman-a i curl-a ga ne primenjuju, pa zahtev može da uspe tamo, a da bude blokiran kada ga pošalje JavaScript stranice.

Šta je preflight zahtev?

Za zahteve koji nisu jednostavni, poput JSON POST-a ili zahteva sa zaglavljem Authorization, pregledač prvo šalje OPTIONS zahtev i pita server koje metode i zaglavlja su dozvoljeni. Ako taj OPTIONS zahtev ne uspe ili nema ispravna zaglavlja, pravi zahtev se uopšte ne šalje.

Mythex · Pricing · Pravite bilo šta uz AI · Šabloni za sajtove i aplikacije · Mythex u poređenju · Rečnik pojmova za pravljenje aplikacija uz AI · Besplatni alati za pravljenje aplikacija uz AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski 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 Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)