CORS to mechanizm przeglądarki, 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 jest mechanizmem 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 tego nie wytłumaczył.
Kod generowany przez AI plus publiczne wdrożenie to miejsce, w którym większości ludzi CORS eksploduje w twarz. Na localhost wszystko działało, bo frontend i backend żyli pod tym samym adresem. Po deploy'u — są na różnych domenach i przeglądarka blokuje zapytania.
Ten artykuł to praktyczny poradnik krok po kroku. Wyjaśniamy, 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.
CORS (Cross-Origin Resource Sharing) to mechanizm bezpieczeństwa przeglądarki, 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 jest pytanie: «Hej serwer, czy frontend z domeny X może Ci wysyłać zapytania typu 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ę.
CORS jest mechanizmem przeglądarki. Za każdym razem, gdy próbujemy wysłać zapytanie do innego hosta, przeglądarka pyta, czy wolno jej to zrobić. Dlatego Postman działa, a Twoja przeglądarka nie — Postman nie jest przeglądarką i nie stosuje tej reguły.
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: pozwolenie AI «naprawić CORS» przepisało kod serwera, zepsuło importy, selekty z bazy danych i kształt odpowiedzi. Trzy dni na cofnięcie tego, co AI zrobiło w sekundy.
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 AI robi:
Access-Control-Allow-Origin: * wszędzie — wildcard zamiast konkretnych domen. Niebezpieczne w produkcji.OPTIONS — preflight zostaje bez odpowiedzi, więc przeglądarka blokuje wszystko.mode: 'no-cors' do fetch po stronie frontendu — to chowa problem, a nie go naprawia. Odpowiedź staje się «opaque» i nie można odczytać żadnych danych.Kiedy coś się psuje, ludzie reagują naturalnie: promptują dalej. «Napraw to». «Teraz tamto nie działa». «Cofnij ostatnią zmianę, ale zachowaj poprawkę CORS». Każdy kolejny prompt pogarsza sytuację, bo AI nie pamięta, dlaczego kod wyglądał tak, jak wyglądał.
Pozwolenie AI «naprawić CORS» przepisało kod serwera, zepsuło importy, selekty z bazy danych i format odpowiedzi. Trzy dni na cofnięcie tego, co AI zrobiło w sekundy. Nie promptuj dalej — zatrzymaj się i zrozum problem.
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. Otwieraj zakładkę Network w DevTools, 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 Twój serwer się wysypał — i bo 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.
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:
A oto co zazwyczaj generuje AI, kiedy prosisz o «naprawienie CORS». Wygląda prosto, ale jest pełne problemów:
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.
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:
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.
Jednocześnie zablokuj kształt odpowiedzi JSON — każdy endpoint powinien zwracać dane w tym samym formacie. Trzymaj plik wejściowy (entry file) jak najkrótszy — powinien tylko importować middleware i uruchamiać serwer. Cała logika biznesowa idzie 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.
Czasami wszystko wygląda poprawnie, a CORS i tak nie działa. Oto najczęstsze pułapki:
https://mojaapka.com to nie to samo co https://www.mojaapka.com. Uważaj też na trailing slash — przeglądarka wysyła nagłówek Origin bez końcowego ukośnika, więc jeśli Twoja lista dozwolonych zawiera https://mojaapka.com/, porównanie stringów nie zadziała.no-cors w 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.http:// i https:// 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.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, nie problem logiki kodu. AI świetnie pisze logikę. Źle rozumie kontekst wdrożeniowy.
Oto powtarzające się wzorce, które widzę u klientów:
* w produkcji — co nie tylko jest niebezpieczne, ale uniemożliwia użycie credentials (ciasteczek, tokenów) w zapytaniach.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.credentials: 'include' w fetch, serwer musi zwrócić Access-Control-Allow-Credentials: true i nie może używać wildcard * jako origin. AI prawie nigdy nie rozumie tej zależności.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.
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 jeden jest niespełniony, aplikacja może się wysypać w sposób, który jest trudny do zdiagnozowania.
* w produkcji. Wymień każdą domenę, z której Twój frontend może wysyłać zapytania.Access-Control-Allow-Credentials: true i nie możesz używać wildcard origin.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.
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ą.
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ą.
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.
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.
Błędy CORS to często tylko wierzchołek góry lodowej. Jeśli Twoja aplikacja AI ma problemy po wdrożeniu, porozmawiajmy — pomożemy Ci przejść od prototypu do produkcji.
Zarezerwuj bezpłatną rozmowę →