Poradniki

Jak naprawić błędy CORS (i dlaczego się pojawiają)

Błąd CORS oznacza, że Twoja strona internetowa próbowała odczytać odpowiedź z innego originu (innej domeny, portu lub protokołu), a tamten serwer nie wysłał nagłówków zezwalających na to. Przeglądarki blokują odpowiedź, żeby chronić użytkowników. Naprawiasz to na serwerze: zwracasz nagłówek Access-Control-Allow-Origin dla originu Twojej strony i obsługujesz żądania preflight OPTIONS — albo unikasz problemu, wysyłając żądanie przez własny backend na tej samej domenie.

To jeden z najbardziej mylących błędów w tworzeniu stron, bo żądanie często dociera do serwera bez problemu. Ten przewodnik wyjaśnia, co się dzieje, i jak naprawić każdy wariant.

Co oznacza "origin"

Origin to połączenie protokołu, domeny i portu:

URLOrigin
https://myapp.com/dashboardhttps://myapp.com
https://api.myapp.com/usershttps://api.myapp.com (inna subdomena, czyli inny origin)
http://localhost:5173http://localhost:5173
http://localhost:3000http://localhost:3000 (inny port, czyli inny origin)

Przeglądarki stosują politykę tego samego originu (same-origin policy): JavaScript na stronie może swobodnie odczytywać odpowiedzi ze swojego originu, ale nie z innych. CORS (Cross-Origin Resource Sharing) to mechanizm, dzięki któremu serwer może wyrazić zgodę: "odpowiedzi ode mnie mogą odczytywać strony z tych originów".

Dwie konsekwencje zaskakują ludzi:

  • Żądanie często dociera do serwera. CORS zwykle blokuje Twojemu kodowi odczyt odpowiedzi, a nie odebranie żądania przez serwer. POST mógł zostać zapisany, mimo że zobaczyłeś błąd.
  • Egzekwują go tylko przeglądarki. curl, Postman i kod po stronie serwera ignorują CORS całkowicie. Dlatego "działa w Postmanie" nic nie mówi o CORS.

Krok 1: Przeczytaj dokładny błąd

Otwórz narzędzia deweloperskie (prawy przycisk → Zbadaj), przejdź do Konsoli i przeczytaj pełny komunikat. Sformułowanie Chrome mówi, z jakim problemem masz do czynienia:

Komunikat zawieraCo jest nie tak
No 'Access-Control-Allow-Origin' header is presentSerwer w ogóle nie wysłał nagłówka albo żądanie zawiodło, zanim dotarło do Twojego kodu CORS (np. 404 lub 500)
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied originSerwer zezwala na inny origin niż Twój
Response to preflight request doesn't pass access control checkPreflight OPTIONS się nie powiódł
...must not be the wildcard '*' when the request's credentials mode is 'include'Wysyłasz ciasteczka, a serwer odpowiedział *
Request header field authorization is not allowedSerwer nie wymienił tego nagłówka w Access-Control-Allow-Headers

Następnie otwórz zakładkę Sieć, znajdź nieudane żądanie (i ewentualne żądanie OPTIONS przed nim) i sprawdź jego kod statusu oraz nagłówki odpowiedzi.

Najpierw sprawdź kod statusu. Wiele "błędów CORS" to w rzeczywistości błąd serwera w przebraniu. Jeśli serwer się wysypie albo zwróci 404, jego odpowiedź o błędzie często nie ma nagłówków CORS, więc przeglądarka zgłasza CORS zamiast prawdziwego problemu. Napraw błąd 500 lub 404, a błąd CORS może zniknąć.

Krok 2: Zdecyduj, czy w ogóle powinieneś wywoływać to API z przeglądarki

Zanim dodasz nagłówki, zapytaj: czy przeglądarka powinna w ogóle wywoływać to API bezpośrednio?

  • API firmy trzeciej wymagające klucza sekretnego (OpenAI, klucz sekretny Stripe, większość usług mailowych) nigdy nie powinno być wywoływane z przeglądarki. Klucz byłby widoczny dla każdego odwiedzającego. Wywołuj je z backendu, a problem CORS zniknie, bo żądania serwer–serwer nie podlegają CORS. Zobacz jak chronić klucze API.
  • API firmy trzeciej, którą kontrolujesz, a które nie wysyła nagłówków CORS, nie da się naprawić po swojej stronie. Wywołuj je z backendu.
  • Twoje własne API możesz naprawić, poprawnie je skonfigurowując. Czytaj dalej.

Krok 3: Napraw to na swoim serwerze

Serwer musi dodawać właściwe nagłówki do swoich odpowiedzi, także tych z błędami.

Dla właściwego żądania wyślij:

  • Access-Control-Allow-Origin: https://myapp.com (dokładny origin frontendu, bez końcowego ukośnika)
  • Vary: Origin, jeśli wartość zależy od tego, który origin pyta

Dla preflight OPTIONS odpowiedz statusem sukcesu (200 lub 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 (każdy własny nagłówek, który wysyłasz)
  • Opcjonalnie Access-Control-Max-Age: 600, żeby przeglądarka zapamiętała preflight na pewien czas

Większość frameworków ma pakiet lub ustawienie, które to robi. W Express — pakiet cors; w FastAPI — CORSMiddleware; w ASP.NET Core — AddCors; w Spring — @CrossOrigin lub konfiguracja CORS. Typowa konfiguracja w Express:

import cors from "cors";

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

Obsługę CORS umieść przed swoimi trasami i uwierzytelnianiem, tak aby żądania preflight (które nie niosą logowania) nie były odrzucane błędem 401.

W narzędziu do budowania z AI opisz konfigurację precyzyjnie:

Frontend pod adresem https://myapp.com wywołuje API pod https://api.myapp.com i dostaje "Response to preflight request doesn't pass access control check". Skonfiguruj CORS w API tak, by zezwalało dokładnie na https://myapp.com i origin podglądu, zezwalało na GET, POST, PATCH, DELETE z nagłówkami Content-Type i Authorization, obsługiwało OPTIONS przed uwierzytelnianiem i dołączało nagłówki CORS także do odpowiedzi błędów.

Krok 4: Obsłuż ciasteczka i dane uwierzytelniające

Jeśli Twój frontend wysyła ciasteczka (np. sesję logowania) do innego originu, obie strony muszą się zgadzać:

  • Frontend ustawia credentials: "include" w fetch albo withCredentials: true w axios.
  • Serwer wysyła Access-Control-Allow-Credentials: true.
  • Nagłówek Access-Control-Allow-Origin serwera musi być dokładnym originem, a nie *.

Ciasteczka międzystronowe wymagają też SameSite=None; Secure, a niektóre przeglądarki dodatkowo ograniczają ciasteczka stron trzecich. To kolejny powód, by preferować podejście z kroku 5.

Krok 5: Unikaj CORS dzięki konfiguracji z tej samej domeny

Często najczystszą naprawą jest niewykonywanie żądań między originami w ogóle. Serwuj API z tego samego originu co strona, na przykład pod https://myapp.com/api/...:

  • W developmencie większość serwerów deweloperskich potrafi działać jako proxy. Ustawienie server.proxy w Vite może przekazywać /api do Twojego backendu na innym porcie, więc przeglądarka rozmawia tylko z jednym originem.
  • Na produkcji kieruj /api do backendu przez ustawienia rewrite lub proxy hosta albo serwuj frontend i API z jednego serwera.

Frontend wywołuje wtedy ścieżkę względną, np. fetch("/api/orders"). Nie ma żądania między originami, nie ma preflightu między originami i nie ma kłopotów z ciasteczkami. Nie musisz też wpisywać na sztywno domeny API, która różni się między podglądem a produkcją.

Zmień frontend tak, by wywoływał backend ścieżkami względnymi /api zamiast pełnego adresu, i skonfiguruj proxy deweloperskie tak, by /api przekazywało do serwera API. Potem usuń ustawienia CORS, które już nie są potrzebne.

Czego nie robić

  • mode: "no-cors" w fetch. Niczego nie omija; daje Twojemu kodowi pustą, nieczytelną odpowiedź.
  • Rozszerzenia przeglądarki wyłączające CORS. Zmieniają tylko Twoją przeglądarkę. Każdy odwiedzający nadal zobaczy błąd.
  • Publiczne usługi "proxy CORS" w prawdziwych aplikacjach. Mogą czytać i zmieniać wszystko, co przez nie przechodzi, i potrafią przestać działać.
  • Access-Control-Allow-Origin: * na API używającym logowania. I tak nie działa z danymi uwierzytelniającymi, a dla prywatnych danych to zły domyślny wybór.
  • Odbijanie dowolnego nagłówka Origin z włączonymi danymi uwierzytelniającymi. Pozwala dowolnej stronie wysyłać żądania w imieniu zalogowanych użytkowników. Używaj listy dozwolonych.

Typowe przyczyny w aplikacjach tworzonych z AI

SytuacjaNaprawa
Frontend wywołuje API firmy trzeciej z kluczem sekretnymPrzenieś wywołanie do backendu
Działa w podglądzie, nie działa na opublikowanej domenieDodaj originy opublikowanej i własnej domeny do listy dozwolonych albo użyj względnych ścieżek /api
Błąd tylko przy POST, PUT lub DELETEPreflight nieobsłużony; dodaj obsługę OPTIONS i dozwolone nagłówki
Błąd pojawił się po dodaniu logowaniaDane uwierzytelniające wymagają dokładnego originu i Allow-Credentials
"Błąd CORS", ale zakładka Sieć pokazuje 500Najpierw napraw błąd serwera
Adres API zakodowany na sztywno jako localhostUżywaj ścieżek względnych lub ustawienia dla każdego środowiska

CORS w Mythex

Kiedy projekt Mythex ma stronę i serwer API, oba działają jako usługi w tym samym projekcie, a w podglądzie możesz przełączać się między nimi. Poproszenie agenta, by frontend wywoływał backend przez względną ścieżkę /api, przekazywaną przez proxy w developmencie, pozwala uniknąć większości problemów z CORS. Jeśli jednak naprawdę potrzebujesz wywołań między originami, podaj agentowi dokładny błąd z konsoli i zaangażowane originy. Sprawdź wynik też na opublikowanej aplikacji, bo jej adres różni się od podglądu. Zobacz Aplikacje wieloserwisowe i Backendy API w dokumentacji oraz nasze przewodniki jak debugować aplikację zbudowaną z AI i frontend a backend.

Lista kontrolna CORS

  • Przeczytano pełny błąd w konsoli i kod statusu nieudanego żądania
  • Wykluczono ukryty błąd 404 lub 500
  • API z kluczami sekretnymi wywoływane z backendu, nie z przeglądarki
  • Serwer wysyła Access-Control-Allow-Origin z dokładnymi dozwolonymi originami
  • Preflight OPTIONS obsłużony z dozwolonymi metodami i nagłówkami, przed uwierzytelnianiem
  • Nagłówki CORS obecne także w odpowiedziach błędów
  • Dane uwierzytelniające: dokładny origin, Allow-Credentials: true, właściwe ustawienia ciasteczek
  • Origin podglądu, opublikowanej i własnej domeny objęte konfiguracją albo użyto względnych ścieżek /api
  • Bez no-cors, publicznych proxy ani odbijania dowolnego originu

Pytania

Co oznacza błąd CORS?

Twoja strona, załadowana z jednego originu, próbowała odczytać odpowiedź z innego originu, a odpowiedź tego serwera nie zawierała nagłówków, które na to zezwalają. Przeglądarka blokuje Twojemu kodowi odczyt odpowiedzi. Rozwiązanie leży po stronie serwera albo w tym, jak kierowane jest żądanie, a nie w kodzie frontendu.

Czy mogę naprawić błąd CORS po stronie frontendu?

Nie w porządny sposób. Ustawienia typu mode: 'no-cors' tylko ukrywają odpowiedź przed Twoim kodem. Naprawiasz to, sprawiając, że serwer wysyła właściwy nagłówek Access-Control-Allow-Origin, albo wywołując API z własnego backendu lub proxy z tej samej domeny.

Czy Access-Control-Allow-Origin: * jest bezpieczne?

Jest w porządku dla publicznych danych, które może odczytać każdy, np. publicznego API bez logowania. Nie działa z ciasteczkami ani innymi danymi uwierzytelniającymi, a dla prywatnych API lepiej wymienić dokładne dozwolone originy.

Dlaczego żądanie działa w Postmanie lub curl, ale nie w przeglądarce?

CORS egzekwują wyłącznie przeglądarki. Narzędzia takie jak Postman czy curl go nie stosują, więc żądanie może się tam powieść, a mimo to zostać zablokowane, gdy wykona je JavaScript strony.

Czym jest żądanie preflight?

Przy żądaniach, które nie są proste, na przykład przy POST z JSON-em albo z nagłówkiem Authorization, przeglądarka najpierw wysyła żądanie OPTIONS, pytając serwer, jakie metody i nagłówki są dozwolone. Jeśli to żądanie OPTIONS się nie powiedzie albo nie ma właściwych nagłówków, właściwe żądanie w ogóle nie zostaje wysłane.

Mythex · Pricing · Zbuduj wszystko z AI · Szablony stron i aplikacji · Mythex w porównaniu · Słownik budowania aplikacji z AI · Darmowe narzędzia do budowania aplikacji z 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 ਪੰਜਾਬੀ 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 简体中文 繁體中文(香港) 繁體中文(台灣)