Jak naprawić błędy CORS w aplikacjach generowanych przez AI
CORS to mechanizm przeglądarki, a nie błąd serwera. Dlatego Postman działa, a Twoja wdrożona aplikacja nie. Ten poradnik krok po kroku pokaże Ci, jak to naprawić właściwie.
CORS to mechanizm przeglądarki. Za każdym razem, gdy Twoja aplikacja próbuje wysłać zapytanie do innego hosta, przeglądarka pyta serwer, czy wolno jej to zrobić. To nie jest błąd w Twoim kodzie — to warstwa bezpieczeństwa wbudowana w każdą przeglądarkę. Problem w tym, że większości ludzi nikt nie wytłumaczył, jak to działa.
Kod generowany przez AI plus publiczne wdrożenie — to właśnie tu większość ludzi się przejedzie na CORS. Na localhost wszystko działało, bo frontend i backend żyły pod tym samym adresem. Po deployu są już na różnych domenach i przeglądarka blokuje zapytania.
Ten artykuł to praktyczny poradnik krok po kroku. Wyjaśniam, czym CORS naprawdę jest, dlaczego narzędzia AI robią to gorzej, i jak to naprawić raz a dobrze — z kodem, który możesz skopiować i użyć od razu.
Czym naprawdę jest CORS
CORS (Cross-Origin Resource Sharing) to mechanizm bezpieczeństwa przeglądarki, a nie błąd serwera. Działa tak: za każdym razem, gdy Twoja aplikacja próbuje wysłać zapytanie HTTP do innego originu (innej domeny, portu lub protokołu), przeglądarka najpierw pyta serwer docelowy, czy jest to dozwolone.
Na localhost Twój frontend i backend zwykle działają pod tym samym adresem — na przykład http://localhost:3000. To jest same-origin — ta sama domena, ten sam port, ten sam protokół. Przeglądarka nie widzi problemu, bo zapytanie idzie do tego samego hosta. Dlatego właśnie na etapie developmentu wszystko działa.
Po wdrożeniu Twój frontend zaczyna żyć na https://mojaapka.com, a backend na https://api.mojaapka.com albo na zupełnie innej domenie. To jest już cross-origin. I tu przeglądarka wchodzi do gry.
Zanim przeglądarka wyśle Twoje prawdziwe zapytanie (POST, PUT, DELETE), najpierw wysyła tak zwane zapytanie preflight — zapytanie OPTIONS do tego samego URL-a. To w gruncie rzeczy pytanie: «Hej serwerze, czy frontend z domeny X może wysyłać Ci zapytania POST z takimi nagłówkami?» Jeśli serwer nie odpowie właściwymi nagłówkami CORS, przeglądarka zablokuje zapytanie zanim je w ogóle wyśle.
Kluczowa sprawa: CORS to mechanizm przeglądarki. Postman, curl, zapytania z serwera — żadne z nich nie stosuje CORS. Dlatego Twoje API może działać doskonale w Postmanie, a w przeglądarce wyrzucać błędy. To nie jest błąd API — to przeglądarka robi swoją robotę.
Kaskada CORS: jak AI robi to gorzej
Typowy scenariusz: widzisz błąd CORS w konsoli. Mówisz AI «napraw CORS». AI zmienia coś w kodzie serwera. Błąd CORS znika — ale teraz coś innego nie działa. Mówisz AI «napraw to». AI przepisuje kolejną część kodu. I tak zaczyna się kaskada.
Widziałem to na własne oczy u klientów: jedno «napraw CORS» rzucone AI przepisało kod serwera, popsuło importy, zapytania do bazy i format odpowiedzi. Trzy dni na cofnięcie tego, co AI zepsuło w kilka sekund.
Problem jest fundamentalny: AI nie rozumie granicy między frontendem a backendem. Nie wie, który kod działa w przeglądarce, a który na serwerze. Kiedy prosisz o naprawę CORS, AI często modyfikuje frontend (dodaje mode: 'no-cors' do fetch) lub zmienia kod serwera w sposób, który psuje wszystko inne.
Najgorsze, co robi AI:
- Dodaje
Access-Control-Allow-Origin: *wszędzie — wildcard zamiast konkretnych domen. Niebezpieczne w produkcji. - Nie obsługuje zapytań
OPTIONS— preflight zostaje bez odpowiedzi, więc przeglądarka blokuje wszystko. - Dodaje
mode: 'no-cors'do fetch po stronie frontendu — to ukrywa problem, a nie go rozwiązuje. Odpowiedź staje się «opaque» i nie da się odczytać żadnych danych. - Zmienia kod, który działa, próbując naprawić coś, czego nie rozumie — to jest właśnie kaskada.
Kiedy coś się psuje, reakcja jest naturalna: promptujesz dalej. «Napraw to». «Teraz tamto nie działa». «Cofnij ostatnią zmianę, ale zostaw poprawkę CORS». Każdy kolejny prompt tylko pogarsza sytuację, bo AI nie pamięta, dlaczego kod wyglądał tak, jak wyglądał.
Naprawa krok po kroku
Krok 1: Sprawdź prawdziwy błąd
Większość ludzi patrzy na błąd CORS w konsoli przeglądarki i myśli, że to problem z CORS. Ale często prawdziwy błąd jest gdzieś indziej. Otwórz w DevTools zakładkę Network, a nie Console.
Znajdź zapytanie, które nie przeszło. Kliknij na nie i sprawdź kod odpowiedzi. Jeśli widzisz 500 Internal Server Error, to znaczy, że Twój serwer się wysypał — a skoro się wysypał, nie dodał nagłówków CORS do odpowiedzi. Przeglądarka widzi brak nagłówka Access-Control-Allow-Origin i pokazuje błąd CORS, ale prawdziwy problem to błąd serwera.
Jeśli endpoint zwraca błąd (500), nagłówek Access-Control-Allow-Origin zwykle nie zostanie dodany. Napraw błąd serwera, a «błąd CORS» zniknie sam.
Krok 2: Prawidłowa konfiguracja CORS (Express.js)
Oto jak powinien wyglądać middleware CORS na serwerze Express.js. Zauważ, że ustawiamy konkretne domeny, a nie wildcard, obsługujemy zapytanie OPTIONS i ustawiamy credentials:
const allowedOrigins = ['https://yourapp.com', 'https://app.yourapp.com'];
function corsMiddleware(req, res, next) {
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
res.setHeader('Access-Control-Allow-Methods',
'GET, POST, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers',
'Content-Type, Authorization');
res.setHeader('Access-Control-Allow-Credentials',
'true');
}
if (req.method === 'OPTIONS')
return res.status(204).end();
next();
}
Krok 3: Jak AI to pisze (źle)
A oto co zazwyczaj generuje AI, kiedy prosisz o «naprawienie CORS». Wygląda prosto, ale jest pełne problemów:
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});
// No OPTIONS handling
// Wildcard in production
// No credentials support
// No Allow-Methods or Allow-Headers
Różnice są kluczowe: wildcard * oznacza, że każda strona na świecie może wysyłać zapytania do Twojego API. Brak obsługi OPTIONS oznacza, że zapytania preflight nie będą działać. Brak Allow-Credentials oznacza, że ciasteczka i tokeny nie będą przesyłane. To nie jest «naprawione» — to jest otwarta furtka bezpieczeństwa.
Krok 4: CORS w Supabase Edge Functions
Jeśli używasz Supabase Edge Functions (Deno), CORS musi być obsłużony ręcznie w każdej funkcji — lub, jeszcze lepiej, scentralizowany w jednym pliku pomocniczym. Oto poprawny wzorzec:
const corsHeaders = {
'Access-Control-Allow-Origin': 'https://yourapp.com',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers':
'Content-Type, Authorization',
};
Deno.serve(async (req) => {
if (req.method === 'OPTIONS')
return new Response(null, {
status: 204,
headers: corsHeaders
});
// Your logic here
const data = { message: 'Hello' };
return new Response(
JSON.stringify(data),
{
headers: {
...corsHeaders,
'Content-Type': 'application/json'
}
}
);
});
Krok 5: Scentralizuj konfigurację CORS
Jeden plik, jedno miejsce. Konfiguracja CORS powinna żyć w jednym miejscu w całym projekcie — nie rozproszona po każdym endpoincie i każdej funkcji. Stwórz plik cors.js (lub cors.ts) i importuj go wszędzie, gdzie jest potrzebny.
Przy okazji ustandaryzuj format odpowiedzi JSON — każdy endpoint powinien zwracać dane w tym samym kształcie. Plik wejściowy (entry file) trzymaj jak najkrótszy — powinien tylko importować middleware i uruchamiać serwer. Cała logika biznesowa trafia do oddzielnych plików.
Dzięki temu, kiedy musisz zmienić dozwolone originy albo dodać nowy nagłówek, robisz to w jednym miejscu, a zmiana działa wszędzie. Brak centralizacji to jeden z głównych powodów, dla których aplikacje AI działają lokalnie, a padają na produkcji.
Krok 6: Debugowanie trudnych przypadków
Czasami wszystko wygląda poprawnie, a CORS i tak nie działa. Oto najczęstsze pułapki:
- Niezgodność URL-i:
https://mojaapka.comto nie to samo cohttps://www.mojaapka.com. Uważaj też na trailing slash — przeglądarka wysyła nagłówekOriginbez końcowego ukośnika, więc jeśli Twoja lista dozwolonych zawierahttps://mojaapka.com/, porównanie stringów nie zadziała. - Tryb
no-corsw fetch: Jeśli ktoś (lub AI) dodałmode: 'no-cors'do zapytania fetch, przeglądarka nie wyrzuci błędu — ale odpowiedź będzie «opaque». Nie można odczytać statusu, nagłówków ani body. To nie jest naprawa — to zamiatanie pod dywan. - Mieszanie HTTP i HTTPS:
http://ihttps://to różne originy. Jeśli Twój frontend jest na HTTPS, a backend na HTTP, CORS zablokuje zapytanie, a na dodatek przeglądarka może zablokować mixed content. - Proxy w development vs. produkcja: Wiele frameworków (React, Vue, Next.js) używa proxy w trybie deweloperskim, który maskuje cross-origin. Na produkcji tego proxy nie ma — i nagle CORS wybucha. Dlatego błędy CORS pojawiają się dopiero po wdrożeniu.
Co narzędzia AI robią źle z CORS
Narzędzia AI do kodowania — Cursor, Claude Code, Copilot i inne — są niezwykle skuteczne w generowaniu kodu. Ale CORS to jeden z obszarów, w których konsekwentnie zawodzą. Dlaczego? Bo CORS to problem konfiguracyjny i architektoniczny, a nie problem logiki kodu. AI świetnie pisze logikę. Źle rozumie kontekst wdrożeniowy.
Oto powtarzające się wzorce, które widzę u klientów:
- AI edytuje kod serwera, kiedy powinno zmieniać tylko frontend — i odwrotnie. Nie rozumie, który kod działa gdzie. Często proponuje zmiany po obu stronach, tworząc niespójność.
- AI używa wildcard
*w produkcji — co nie tylko jest niebezpieczne, ale uniemożliwia użycie credentials (ciasteczek, tokenów) w zapytaniach. - AI nie obsługuje zapytań preflight
OPTIONS— co oznacza, że zapytania POST, PUT i DELETE będą blokowane przez przeglądarkę, nawet jeśli nagłówki CORS są ustawione poprawnie na zwykłych odpowiedziach. - AI nie wie o trybie credentials — kiedy używasz
credentials: 'include'w fetch, serwer musi zwrócićAccess-Control-Allow-Credentials: truei nie może używać wildcard*jako origin. AI prawie nigdy nie rozumie tej zależności. - Ludzie poprawiają promptami, zamiast naprawić strukturę — kiedy CORS nie działa, naturalny odruch to «napraw to». Ale każdy kolejny prompt bez zrozumienia problemu generuje więcej kodu, który problem maskuje, a nie rozwiązuje. To właśnie ta kaskada, o której pisałem wyżej.
Najlepsza strategia: nie proś AI o naprawę CORS. Zrozum problem sam, napisz konfigurację ręcznie (albo użyj kodu z tego artykułu) i powiedz AI, żeby nie ruszało plików konfiguracyjnych.
Checklista CORS gotowa na produkcję
Zanim wdrożysz swoją aplikację, przejdź przez te punkty. Każdy z nich to potencjalne źródło błędów CORS na produkcji. Jeśli choć jeden zostanie pominięty, aplikacja może się wysypać w sposób trudny do zdiagnozowania.
- Konkretne dozwolone originy. Nigdy nie używaj
*w produkcji. Wymień każdą domenę, z której Twój frontend może wysyłać zapytania. - Obsługuj zapytania OPTIONS jawnie. Każdy endpoint musi odpowiadać na preflight z kodem 204 i właściwymi nagłówkami CORS. Bez tego POST/PUT/DELETE nie przejdą.
- Ustaw Allow-Methods i Allow-Headers. Przeglądarka sprawdza, czy metoda i nagłówki, których używasz, są dozwolone. Jeżeli ich nie wypiszesz, zapytanie zostanie zablokowane.
- Obsłuż credentials poprawnie. Jeżeli używasz ciasteczek lub tokenów, musisz ustawić
Access-Control-Allow-Credentials: truei nie możesz używać wildcard origin. - Scentralizuj CORS w jednym pliku pomocniczym. Jedna zmiana, jedno miejsce. Nie rozrzucaj konfiguracji po plikach.
- Testuj z wdrożonego frontendu, nie z localhost. CORS zachowuje się inaczej na localhost. Testuj z prawdziwej domeny po każdym wdrożeniu.
- Błędy 5xx też muszą zwracać nagłówki CORS. Jeżeli Twój error handler nie dodaje nagłówków CORS, każdy błąd serwera będzie wyglądał jak błąd CORS w przeglądarce.
- Brak niezgodności URL-i. Sprawdź trailing slashes, www vs. non-www, http vs. https. Każda niezgodność to inny origin.
- Strukturalne logowanie błędów CORS. Loguj odrzucone zapytania z originem, metodą i nagłówkami. Bez tego debugowanie na produkcji to strzał w ciemno.
- Autotest po każdym wdrożeniu. Prosty skrypt, który wysyła cross-origin zapytanie do Twojego API i sprawdza, czy odpowiedź zawiera właściwe nagłówki CORS.
Często zadawane pytania
Dlaczego moja aplikacja działa na localhost, ale dostaje błędy CORS na produkcji?
Na localhost frontend i backend zwykle działają pod tym samym adresem (np. http://localhost:3000), więc przeglądarka traktuje to jako same-origin i nie stosuje reguł CORS. Po wdrożeniu frontend i backend są na różnych domenach — to jest cross-origin i przeglądarka zaczyna sprawdzać nagłówki CORS. Dodatkowo, wiele frameworków używa proxy w trybie deweloperskim, który maskuje cross-origin — ten proxy nie istnieje na produkcji.
Czy powinienem używać Access-Control-Allow-Origin: * ?
Tylko dla w pełni publicznych API, które nie wymagają uwierzytelniania — np. publiczne dane pogodowe czy kursy walut. W każdym innym przypadku używaj listy konkretnych domen. Pamiętaj: wildcard * i Access-Control-Allow-Credentials: true nie mogą istnieć razem. Przeglądarka odrzuci odpowiedź. Jeśli Twoja aplikacja używa ciasteczek, tokenów JWT lub jakiejkolwiek formy sesji, wildcard nie jest opcją.
Czy CORS to problem frontendu czy backendu?
CORS to konfiguracja backendu, która jest wyzwalana przez frontend. Błąd pojawia się w przeglądarce (frontend), ale rozwiązanie leży na serwerze (backend). Serwer musi zwrócić właściwe nagłówki Access-Control-Allow-*, żeby przeglądarka pozwoliła na zapytanie. Nie da się «naprawić CORS» samymi zmianami w kodzie frontendu — jedyne, co można zrobić po stronie klienta, to ukryć problem (np. mode: 'no-cors'), co jest gorszą opcją.
Dlaczego Postman działa, a moja przeglądarka nie?
Postman nie jest przeglądarką. Przeglądarki wymuszają CORS — klienty API tego nie robią. Postman, curl, Insomnia, requesty z serwera — żadne z nich nie wysyła zapytań preflight ani nie sprawdza nagłówków Access-Control-Allow-Origin. To czysty mechanizm przeglądarkowy. Jeżeli Twoje API działa w Postmanie, ale nie w przeglądarce, to 100% problem z konfiguracją CORS na serwerze — nie z samym API.
AI naprawiło CORS, ale teraz inne rzeczy nie działają
To jest właśnie kaskada CORS. AI nie rozumie kontekstu Twojego projektu. Kiedy prosisz je o naprawę CORS, często modyfikuje pliki, które nie powinny być ruszone — zmienia importy, modyfikuje kształt odpowiedzi, przepisuje middleware. Każda kolejna poprawka pogarsza sytuację. Rozwiązanie: cofnij się do stanu sprzed «naprawy» AI (użyj git), zrozum problem CORS używając tego artykułu, i napisz konfigurację ręcznie. Nie pozwalaj AI edytować plików konfiguracyjnych CORS.
CORS naprawiony, ale coś dalej nie działa?
Błędy CORS to często tylko wierzchołek góry lodowej. Jeśli Twoja aplikacja AI ma problemy po wdrożeniu, porozmawiajmy — pomogę Ci przejść od prototypu do produkcji.
Zarezerwuj bezpłatną rozmowę →