Průvodci

Jak opravit chyby CORS (a proč vznikají)

Chyba CORS znamená, že se vaše webová stránka pokusila číst odpověď z jiného původu (jiné domény, portu nebo protokolu) a tento server neposlal hlavičky, že je to povoleno. Prohlížeče odpověď zablokují, aby chránily uživatele. Opravuje se na serveru: vrácením hlavičky Access-Control-Allow-Origin pro původ vašeho webu a zpracováním preflight požadavků OPTIONS. Nebo se jí vyhnete tak, že požadavek pošlete přes vlastní backend na stejném původu.

Je to jedna z nejmatoucích chyb ve vývoji webu, protože požadavek na server často dorazí v pořádku. Tento návod vysvětluje, co se děje, a jak opravit každou variantu.

Co znamená „původ“

Původ je kombinace protokolu, domény a portu:

URLPůvod
https://mojeapp.cz/dashboardhttps://mojeapp.cz
https://api.mojeapp.cz/usershttps://api.mojeapp.cz (jiná subdoména, tedy jiný původ)
http://localhost:5173http://localhost:5173
http://localhost:3000http://localhost:3000 (jiný port, tedy jiný původ)

Prohlížeče dodržují politiku stejného původu: JavaScript na stránce si volně přečte odpovědi ze svého vlastního původu, ale ne z cizích. CORS (Cross-Origin Resource Sharing) je systém, kterým se server může rozhodnout: „odpovědi ode mě smějí číst stránky z těchto původů.“

Dva důsledky lidi často překvapí:

  • Požadavek často server dostane. CORS obvykle blokuje, aby váš kód četl odpověď, ne aby server přijal požadavek. POST může být uložen, i když jste viděli chybu.
  • Vynucují ho jen prohlížeče. curl, Postman a kód na serveru CORS ignorují úplně. Proto „v Postmanu to funguje“ o CORS nic neříká.

Krok 1: Přečtěte přesnou chybu

Otevřete vývojářské nástroje (pravý klik → Prozkoumat), přejděte na Konzoli a přečtěte celou zprávu. Formulace Chrome ukazuje, jaký problém máte:

Zpráva obsahujeCo je špatně
No 'Access-Control-Allow-Origin' header is presentServer hlavičku vůbec neposlal, nebo požadavek selhal dřív, než dorazil k vašemu CORS kódu (například 404 nebo 500)
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied originServer povoluje jiný původ, než je ten váš
Response to preflight request doesn't pass access control checkPreflight OPTIONS selhal
...must not be the wildcard '*' when the request's credentials mode is 'include'Posíláte cookies a server odpověděl *
Request header field authorization is not allowedServer nevypsal tuto hlavičku v Access-Control-Allow-Headers

Pak otevřete záložku Síť, najděte selhavší požadavek (a případný předchozí požadavek OPTIONS) a podívejte se na jeho stavový kód a hlavičky odpovědi.

Nejdřív zkontrolujte stavový kód. Mnoho „chyb CORS“ je ve skutečnosti chyba serveru v přestrojení. Pokud server spadne nebo vrátí 404, jeho chybová odpověď často nemá CORS hlavičky, takže prohlížeč nahlásí CORS místo skutečného problému. Opravte 500 nebo 404 a chyba CORS může zmizet.

Krok 2: Rozhodněte, zda by to API vůbec měl volat prohlížeč

Než přidáte hlavičky, zeptejte se: má prohlížeč toto API volat přímo?

  • API třetí strany, které vyžaduje tajný klíč (OpenAI, tajný klíč Stripe, většina e-mailových služeb), by se nikdy nemělo volat z prohlížeče. Klíč by viděl každý návštěvník. Volejte ho z backendu a problém s CORS zmizí, protože požadavky server-server nepodléhají CORS. Viz jak chránit API klíče.
  • API třetí strany, které nespravujete, a které neposílá CORS hlavičky, nelze opravit z vaší strany. Volejte ho z backendu.
  • Vaše vlastní API lze opravit správným nastavením. Pokračujte níže.

Krok 3: Opravte to na svém serveru

Server musí do odpovědí přidat správné hlavičky, včetně chybových odpovědí.

Pro samotný požadavek pošlete:

  • Access-Control-Allow-Origin: https://mojeapp.cz (přesný původ vašeho frontendu, bez koncového lomítka)
  • Vary: Origin, pokud hodnota závisí na tom, který původ se ptá

Pro preflight požadavek OPTIONS odpovězte úspěšným stavem (200 nebo 204) a:

  • Access-Control-Allow-Origin: https://mojeapp.cz
  • Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE
  • Access-Control-Allow-Headers: Content-Type, Authorization (každou vlastní hlavičku, kterou posíláte)
  • Volitelně Access-Control-Max-Age: 600, aby prohlížeč preflight chvíli cachoval

Většina frameworků má balíček nebo nastavení, které to dělá. V Express je to balíček cors; ve FastAPI CORSMiddleware; v ASP.NET Core AddCors; ve Springu @CrossOrigin nebo konfigurace CORS. Typické nastavení v Express:

import cors from "cors";

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

Zpracování CORS dejte před své trasy a autentizaci, aby preflight požadavky (které nemají přihlášení) nebyly odmítnuty s 401.

U nástroje s AI popište nastavení přesně:

Frontend na https://mojeapp.cz volá API na https://api.mojeapp.cz a dostává „Response to preflight request doesn't pass access control check“. Nastav CORS na API tak, aby povolilo přesně https://mojeapp.cz a původ náhledu, povolilo GET, POST, PATCH, DELETE s hlavičkami Content-Type a Authorization, zpracovalo OPTIONS před autentizací a CORS hlavičky posílalo i u chybových odpovědí.

Krok 4: Zpracujte cookies a přihlašovací údaje

Pokud frontend posílá cookies (například relaci přihlášení) na jiný původ, musí se obě strany shodnout:

  • Frontend nastaví credentials: "include" u fetch, nebo withCredentials: true u axios.
  • Server pošle Access-Control-Allow-Credentials: true.
  • Access-Control-Allow-Origin na serveru musí být přesný původ, ne *.

Cookies napříč weby také potřebují SameSite=None; Secure, a některé prohlížeče omezují cookies třetích stran ještě dál. To je další důvod, proč dát přednost přístupu z kroku 5.

Krok 5: Vyhněte se CORS nastavením na stejném původu

Často je nejčistší oprava vůbec nedělat požadavky mezi původy. Servírujte API ze stejného původu jako stránka, například na https://mojeapp.cz/api/...:

  • Při vývoji mohou většina vývojových serverů fungovat jako proxy. Nastavení server.proxy ve Vite může přeposílat /api na váš backend na jiném portu, takže prohlížeč komunikuje jen s jedním původem.
  • V produkci směrujte /api na backend přes přepisy nebo proxy nastavení hostingu, nebo servírujte frontend a API z jednoho serveru.

Frontend pak volá relativní cestu jako fetch("/api/orders"). Není žádný požadavek mezi původy, žádný preflight mezi původy a žádné problémy s cookies. Také to znamená, že nemusíte napevno zadávat doménu API, která se liší mezi náhledem a produkcí.

Změň frontend tak, aby volal backend přes relativní cesty /api místo plné URL, a nastav vývojový proxy, aby /api přeposílalo na API server. Potom odstraň CORS nastavení, která už nepotřebujeme.

Čeho se vyvarovat

  • mode: "no-cors" ve fetch. Nic neobchází; dá vašemu kódu prázdnou, nečitelnou odpověď.
  • Rozšíření prohlížeče, která vypínají CORS. Mění jen váš prohlížeč. Každý návštěvník pořád uvidí chybu.
  • Veřejné „CORS proxy“ služby pro skutečné aplikace. Mohou číst a měnit vše, co jimi prochází, a často nefungují.
  • Access-Control-Allow-Origin: * u API, které používá přihlášení. Stejně nefunguje s přihlašovacími údaji a je to špatný výchozí stav pro soukromá data.
  • Odrážení libovolné hlavičky Origin zpět s povolenými přihlašovacími údaji. Umožní to jakémukoli webu dělat požadavky jménem přihlášených uživatelů. Používejte seznam povolených.

Časté příčiny v aplikacích postavených s AI

SituaceOprava
Frontend volá API třetí strany s tajným klíčemPřesuňte volání na backend
Funguje v náhledu, selže na publikované doméněPřidejte publikovaný původ a původ vlastní domény na seznam povolených, nebo použijte relativní cesty /api
Chyba jen u POST, PUT nebo DELETEPreflight není zpracován; přidejte zpracování OPTIONS a povolené hlavičky
Chyba se objevila po přidání přihlášeníPřihlašovací údaje vyžadují přesný původ a Allow-Credentials
„Chyba CORS“, ale záložka Síť ukazuje 500Nejdřív opravte chybu serveru
URL API napevno nastavená na localhostPoužijte relativní cesty nebo nastavení podle prostředí

CORS v Mythex

Když má projekt v Mythex web a API server, oba běží jako služby ve stejném projektu a v náhledu mezi nimi můžete přepínat. Pokud agentovi zadáte, ať frontend volá backend přes relativní cestu /api, která se ve vývoji přeposílá, většina problémů s CORS zmizí. Pokud přesto potřebujete volání mezi původy, dejte agentovi přesnou chybu z konzole a zapojené původy. Výsledek zkontrolujte i na publikované aplikaci, protože její adresa se liší od náhledu. Viz Multi-service apps a API backends v dokumentaci a naše návody jak ladit aplikaci postavenou s AI a frontend vs. backend.

Kontrolní seznam CORS

  • Přečtena celá chyba v konzoli a stavový kód selhavšího požadavku
  • Vyloučena skrytá 404 nebo 500
  • API s tajnými klíči volána z backendu, ne z prohlížeče
  • Server posílá Access-Control-Allow-Origin s přesně povolenými původy
  • Preflight OPTIONS zodpovězen povolenými metodami a hlavičkami, před autentizací
  • CORS hlavičky přítomny i u chybových odpovědí
  • Přihlašovací údaje: přesný původ, Allow-Credentials: true, správná nastavení cookies
  • Pokryty původy náhledu, publikované aplikace i vlastní domény, nebo použity relativní cesty /api
  • Žádné no-cors, veřejné proxy ani zkratky s odrážením libovolného původu

Otázky

Co znamená chyba CORS?

Vaše stránka, načtená z jednoho původu, se pokusila číst odpověď z jiného původu a odpověď toho serveru neobsahovala hlavičky, které to povolují. Prohlížeč vašemu kódu čtení odpovědi zablokuje. Oprava je na serveru nebo v tom, jak je požadavek směrován, ne ve frontendovém kódu.

Můžu chybu CORS opravit z frontendu?

Ne pořádně. Nastavení jako mode: 'no-cors' jen skryjí odpověď před vaším kódem. Opravíte to tak, že server pošle správnou hlavičku Access-Control-Allow-Origin, nebo tím, že API budete volat z vlastního backendu nebo proxy na stejném původu.

Je Access-Control-Allow-Origin: * bezpečné?

Je v pořádku pro veřejná data, která smí číst kdokoli, třeba veřejné API bez přihlášení. Nedá se použít s cookies ani jinými přihlašovacími údaji a u soukromých API byste měli vypsat přesné povolené původy.

Proč požadavek funguje v Postmanu nebo curl, ale ne v prohlížeči?

CORS vynucují jen prohlížeče. Nástroje jako Postman a curl ho neuplatňují, takže požadavek může tam uspět a přitom být zablokován, když ho volá JavaScript stránky.

Co je preflight požadavek?

U požadavků, které nejsou jednoduché, například JSON POST nebo požadavek s hlavičkou Authorization, prohlížeč nejdřív pošle požadavek OPTIONS a zeptá se serveru, jaké metody a hlavičky jsou povoleny. Pokud tento požadavek OPTIONS selže nebo nemá správné hlavičky, skutečný požadavek se vůbec neodešle.

Mythex · Pricing · Vytvořte cokoli s AI · Šablony webů a aplikací · Mythex v porovnání · Slovník tvorby aplikací s AI · Bezplatné nástroje pro tvorbu aplikací s AI · English

English አማርኛ العربية Български বাংলা Bosanski Català 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 Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)