Как да поправите CORS грешки (и защо се появяват)
CORS грешката означава, че вашата уеб страница се е опитала да прочете отговор от друг произход (друг домейн, порт или протокол), а този сървър не е изпратил заглавия, които казват, че е позволено. Браузърите блокират отговора, за да защитят потребителите. Поправяте го на сървъра – като връщате заглавие Access-Control-Allow-Origin за произхода на сайта си и обработвате OPTIONS preflight заявките – или го избягвате, като изпращате заявката през собствения си бекенд на същия произход.
Това е една от най-объркващите грешки в уеб разработката, защото заявката често стига до сървъра без проблем. Това ръководство обяснява какво се случва и как да поправите всеки вариант.
Какво е „произход“
Произходът е комбинация от протокол, домейн и порт:
| URL | Произход |
|---|---|
https://myapp.com/dashboard | https://myapp.com |
https://api.myapp.com/users | https://api.myapp.com (различно поддомейн, значи различен произход) |
http://localhost:5173 | http://localhost:5173 |
http://localhost:3000 | http://localhost:3000 (различен порт, значи различен произход) |
Браузърите следват политиката за същия произход: JavaScript на страницата може свободно да чете отговори от собствения си произход, но не и от други. CORS (Cross-Origin Resource Sharing) е системата, с която сървърът се съгласява: „отговорите ми могат да се четат от страници с тези произходи“.
Два факта изненадват хората:
- Заявката често стига до сървъра. CORS обикновено блокира кода ви да прочете отговора, а не сървърът да получи заявката. POST може да е записан, въпреки че сте видели грешка.
- Прилага се само от браузърите. curl, Postman и серверен код игнорират CORS напълно. Затова „работи в Postman“ не ви казва нищо за CORS.
Стъпка 1: Прочетете точната грешка
Отворете инструментите за разработчици (десен бутон → Inspect), отидете в раздела Console и прочетете цялото съобщение. Формулировката на Chrome показва какъв проблем имате:
| Съобщението съдържа | Какво не е наред |
|---|---|
No 'Access-Control-Allow-Origin' header is present | Сървърът изобщо не е изпратил заглавието или заявката е провалена преди да стигне до CORS кода ви (например 404 или 500) |
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied origin | Сървърът позволява друг произход, различен от вашия |
Response to preflight request doesn't pass access control check | OPTIONS preflight заявката се е провалила |
...must not be the wildcard '*' when the request's credentials mode is 'include' | Изпращате бисквитки, а сървърът отговаря с * |
Request header field authorization is not allowed | Сървърът не е изброил това заглавие в Access-Control-Allow-Headers |
След това отворете раздела Network, намерете провалената заявка (и всяка OPTIONS заявка преди нея) и вижте статус кода и заглавията на отговора.
Първо проверете статус кода. Много „CORS грешки“ всъщност са серверна грешка, маскирана като такава. Ако сървърът се срине или върне 404, отговорът му често няма CORS заглавия и браузърът докладва CORS, вместо истинския проблем. Поправете 500 или 404 грешката и CORS грешката може да изчезне.
Стъпка 2: Решете дали изобщо трябва браузърът да вика това API
Преди да добавяте заглавия, попитайте: трябва ли браузърът да вика това API директно?
- Трето API, което изисква тайна ключ (OpenAI, тайният ключ на Stripe, повечето имейл услуги) никога не трябва да се вика от браузъра. Ключът ще е видим за всеки посетител. Викайте го от бекенда си и CORS проблемът изчезва, защото заявките сървър-към-сървър не подлежат на CORS. Вижте как да пазите API ключовете си в безопасност.
- Трето API, което не контролирате и което не изпраща CORS заглавия, не може да се поправи от вашата страна. Викайте го от бекенда си.
- Вашето собствено API може да се поправи чрез правилна конфигурация. Продължете по-долу.
Стъпка 3: Поправете на сървъра
Сървърът трябва да добавя правилните заглавия към всичките си отговори, включително тези с грешки.
За самата заявка изпратете:
Access-Control-Allow-Origin: https://myapp.com(точният произход на фронтенда ви, без наклонена черта в края)Vary: Origin, ако стойността зависи от това кой произход пита
За preflight OPTIONS заявката отговорете със статус за успех (200 или 204) и:
Access-Control-Allow-Origin: https://myapp.comAccess-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETEAccess-Control-Allow-Headers: Content-Type, Authorization(всяко собствено заглавие, което изпращате)- По желание
Access-Control-Max-Age: 600, за да кешира браузърът preflight заявката известно време
Повечето фреймуърци имат пакет или настройка, която прави това. В Express – пакетът cors; във FastAPI – CORSMiddleware; в ASP.NET Core – AddCors; в Spring – @CrossOrigin или CORS конфигурация. Типична настройка в Express:
import cors from "cors";
app.use(cors({
origin: ["https://myapp.com", "http://localhost:5173"],
credentials: true,
}));
Поставете CORS обработката преди маршрутите и удостоверяването, за да не се отхвърлят preflight заявките (които не носят вход) с 401.
При AI конструктор опишете настройката точно:
Фронтендът на
https://myapp.comвика API наhttps://api.myapp.comи получава „Response to preflight request doesn't pass access control check“. Конфигурирайте CORS на API-то така, че да позволява точноhttps://myapp.comи preview произхода, да разрешава GET, POST, PATCH, DELETE със заглавията Content-Type и Authorization, да обработва OPTIONS преди удостоверяването и да включва CORS заглавията и в отговорите с грешки.
Стъпка 4: Работа с бисквитки и удостоверителни данни
Ако фронтендът ви изпраща бисквитки (например сесия за вход) към друг произход, двете страни трябва да се съгласят:
- Фронтендът задава
credentials: "include"вfetchилиwithCredentials: trueв axios. - Сървърът изпраща
Access-Control-Allow-Credentials: true. Access-Control-Allow-Originна сървъра трябва да е точният произход, а не*.
Междусайтовите бисквитки също изискват SameSite=None; Secure, а някои браузъри ограничават още бисквитките от трети страни. Това е още една причина да предпочитате подхода от стъпка 5.
Стъпка 5: Избегнете CORS с настройка от същия произход
Често най-чистата поправка е да не правите междусайтови заявки изобщо. Сервирайте API-то от същия произход като страницата, например на https://myapp.com/api/...:
- В разработка повечето dev сървъри могат да проксират. Настройката
server.proxyна Vite може да препраща/apiкъм бекенда ви на друг порт, така че браузърът говори само с един произход. - В продукция пренасочете
/apiкъм бекенда през настройките за пренаписване или прокси на хостинга, или сервирайте фронтенда и API-то от един сървър.
Тогава фронтендът вика относителен път като fetch("/api/orders"). Няма междусайтова заявка, няма preflight между произходи и няма проблеми с бисквитките. Освен това не закодирате в кода домейн на API, който се различава между преглед и продукция.
Променете фронтенда да вика бекенда с относителни пътища /api вместо пълен URL и настройте dev прокси, така че /api да препраща към API сървъра. После премахнете CORS настройките, които вече не са нужни.
Какво да не правите
mode: "no-cors"въвfetch. Нищо не заобикаля; дава на кода ви празен, нечетим отговор.- Браузърни разширения, които изключват CORS. Те променят само вашия браузър. Всеки посетител пак вижда грешката.
- Публични услуги „CORS прокси“ за реални приложения. Могат да четат и променят всичко, което минава през тях, и понякога спират да работят.
Access-Control-Allow-Origin: *за API с вход. Така или иначе не работи с удостоверителни данни и е грешното подразбиране за частни данни.- Връщане на произволен
Originзаглавие обратно с разрешени удостоверителни данни. Това позволява на всеки сайт да прави заявки от името на логнатите ви потребители. Използвайте списък с разрешени.
Чести причини в приложения, създадени с AI
| Ситуация | Поправка |
|---|---|
| Фронтендът вика трето API с тайн ключ | Преместете заявката в бекенда |
| Работи в преглед, но не и в публикуваното приложение | Добавете публикувания и персоналния домейн в списъка с разрешени или използвайте относителни пътища /api |
| Грешка само при POST, PUT или DELETE | Preflight не е обработен; добавете обработка на OPTIONS и разрешените заглавия |
| Грешката се появи след добавяне на вход | Бисквитките изискват точен произход и Allow-Credentials |
| „CORS грешка“, но в раздела Network се вижда 500 | Първо поправете серверната грешка |
API URL е записан твърдо като localhost | Използвайте относителни пътища или настройка за всяка среда |
CORS в Mythex
Когато Mythex проект има уебсайт и API сървър, и двата работят като услуги в същия проект и можете да превключвате между тях в прегледа. Ако помолите агента фронтендът да вика бекенда през относителен път /api, проксиран при разработка, се избягват повечето CORS проблеми. Ако все пак са ви нужни междусайтови заявки, дайте на агента точната грешка от конзолата и участващите произходи. Проверете резултата и в публикуваното приложение, защото адресът му е различен от този в прегледа. Вижте Многоуслугови приложения и API бекенди в документацията, както и нашите ръководства за отстраняване на грешки в приложение, създадено с AI и фронтенд срещу бекенд.
Списък за проверка на CORS
- Прочетена е цялата грешка от конзолата и статус кодът на провалената заявка
- Изключена е скрита 404 или 500 грешка
- API-та с тайни ключове се викат от бекенда, не от браузъра
- Сървърът изпраща
Access-Control-Allow-Originс точни разрешени произходи -
OPTIONSpreflight е обработен с разрешени методи и заглавия, преди удостоверяването - CORS заглавията присъстват и в отговорите с грешки
- Удостоверителни данни: точен произход,
Allow-Credentials: trueи правилни настройки на бисквитките - Покрити са произходите на преглед, публикуване и персонален домейн, или се използват относителни пътища
/api - Няма
no-cors, публични прокси или шорткъти с отразяване на произволен произход
Въпроси
Какво означава CORS грешка?
Вашата страница, заредена от един произход, се е опитала да прочете отговор от друг произход, а сървърът на този произход не е изпратил заглавки, които да го позволяват. Браузърът блокира кода ви да прочете отговора. Поправката е на сървъра или в начина, по който се насочва заявката, а не във фронтенд кода.
Мога ли да поправя CORS грешка от фронтенда?
Не по същество. Настройки като mode: 'no-cors' само скриват отговора от кода ви. Поправката е сървърът да изпраща правилното заглавие Access-Control-Allow-Origin или да извиквате API-то от собствения си бекенд или от прокси от същия произход.
Безопасно ли е Access-Control-Allow-Origin: *?
Добре е за публични данни, които всеки може да чете, например публично API без вход. Не може да се ползва с бисквитки или други удостоверителни данни, а за частни API трябва да изброите точно допустимите произходи.
Защо заявката работи в Postman или curl, но не и в браузъра?
CORS се прилага само от браузърите. Инструменти като Postman и curl не го прилагат, така че заявката може да успее там и пак да бъде блокирана, когато JavaScript на страницата я изпрати.
Какво е preflight заявка?
За заявки, които не са прости, например JSON POST или заявка със заглавие Authorization, браузърът първо изпраща OPTIONS заявка, за да попита сървъра кои методи и заглавия са разрешени. Ако тази OPTIONS заявка се провали или няма правилните заглавия, истинската заявка никога не се изпраща.