Начало
» Основни познания
»
Как да поправите липсващия CORS заглавен ред Access-Control-Allow-Origin в Express.js
Как да поправите липсващия CORS заглавен ред Access-Control-Allow-Origin в Express.js
Ако браузърът показва съобщение CORS header 'Access-Control-Allow-Origin' missing, важната подсказка не е, че Express.js не е получил заявката. Браузърът ви казва, че отговорът не е включил CORS заглавен ред, който да упълномощава произхода на страницата да прочете този отговор. Следователно решението принадлежи на сървъра или на прокси сървър, който контролирате, а не на някаква случайна настройка от страната на клиента.
Илюстративен пример, използван в това ръководство: представете си таблица с задачи, работеща на http://localhost:5173, която извиква Express API на http://localhost:3000/api/tasks. Браузърът блокира JavaScript да прочете отговора от API, защото API не връща Access-Control-Allow-Origin. Това е хипотетичен учебен пример, а не твърдение за реален тест, продукт или внедряване.
Както е проверено на 11 септември 2026 г., официалната документация за Express CORS middleware посочва версия 2.8.6 на cors и я описва като middleware, което задава CORS заглавни редове в отговора. Текущият списък с пакети на Express е от серията 5.x, затова това ръководство предпочита middleware на ниво приложение, вместо да разчита на по-стари шаблони за маршрути с wildcard.
Какво всъщност означава грешката
Уеб страницата има произход (origin), съставен от схемата, хоста и порта ѝ. В примера http://localhost:5173 и http://localhost:3000 са различни произходи, защото портовете им се различават. Политиката на браузъра за един и същи произход (same-origin policy) обикновено предотвратява JavaScript от един произход да чете ресурси от друг, освен ако целевият сървър не върне подходящи заглавни редове за Cross-Origin Resource Sharing (CORS).
Документацията на MDN за тази конкретна грешка обяснява, че в отговора липсва задължителният заглавен ред Access-Control-Allow-Origin. Ако контролирате сървъра, трябва да конфигурирате произхода на заявяващия сайт като разрешен произход. За публични API без удостоверяване (non-credentialed), * може да е подходящ; за частни или удостоверяващи API използвайте конкретни доверени произходи. Вижте обяснението на MDN за липсващата грешка Access-Control-Allow-Origin.
Стъпка 1: Потвърдете, че CORS е проблемът, и идентифицирайте точния произход
Илюстрация, генерирана от AI, а не реален екранен снимка: браузърът докладва, че в отговора на Express липсва Access-Control-Allow-Origin.
Отворете инструментите за разработчици на браузъра и проверете както панелите Console, така и Network. Запишете точно произхода на фронтенда, както го изпраща браузърът. В нашия илюстративен случай това е http://localhost:5173.
Не свеждайте произхода само до име на хост. Това са различни произходи: http://localhost:5173, http://localhost:3000, http://127.0.0.1:5173 и https://localhost:5173. Списъкът с разрешени в производствена среда трябва също да разграничава https://app.example.com от други схеми, хостове, портове или поддомейни, освен ако не ги разрешавате умишлено.
Ако отговорът на API е 404, 500, пренасочване, грешка при удостоверяване или страница с грешка, генерирана от прокси, проверете и този отговор. CORS заглавните редове трябва да присъстват в отговора, който браузърът всъщност получава. Поправянето на маршрут в приложението няма да помогне, ако обратен прокси, CDN, балансировчик на натоварването или обработчик на грешки връща различен отговор без заглавния ред.
Стъпка 2: Инсталирайте и заредете официалния Express CORS middleware
Илюстрация, генерирана от AI, а не реален екранен снимка: инсталирайте cors middleware, поддържан от Express, и го заредете в сървъра.
За повечето Express приложения най-малко податливото на грешки решение е cors middleware, поддържано от проекта Express. Официалната страница с middleware на Express го изброява сред middleware, поддържани от екипа на Express.js. Инсталирайте го във вашия API проект:
Стъпка 3: Разрешете произхода на фронтенда умишлено
Илюстрация, генерирана от AI, а не реален екранен снимка: конфигурирайте CORS преди маршрутите на API, за да получи разрешеният произход заглавния ред на отговора.
За хипотетичната таблица конфигурирайте точния произход за разработка преди маршрутите, които имат нужда от CORS:
Поставянето на app.use(cors(corsOptions)) преди маршрутите на API е важно, защото Express обработва middleware в ред. Middleware трябва да има възможност да добави заглавни редове на отговора, преди маршрут или по-ранен middleware да прекрати заявката.
За наистина публично API, което не използва удостоверяващи данни, app.use(cors()) използва поведението по подразбиране на middleware за разрешен произход. Това е удобно, но не трябва да е вашият автоматичен избор за производство. MDN препоръчва ограничаването на Access-Control-Allow-Origin до минималните необходими произходи и ресурси. Вижте ръководството за сигурност на MDN за CORS.
Разрешете няколко известни произхода, без да разрешавате на всички
Честа производствена конфигурация има локален фронтенд, фронтенд за staging и фронтенд за производство. Използвайте списък с разрешени и валидирайте входящия произход:
const allowedOrigins = new Set([
'http://localhost:5173',
'https://staging.example.com',
'https://app.example.com'
]);
const corsOptions = {
origin(origin, callback) {
if (!origin || allowedOrigins.has(origin)) {
callback(null, true);
return;
}
callback(new Error('Origin not allowed by CORS'));
}
};
app.use(cors(corsOptions));
Клонът !origin позволява на клиенти, които не изпращат заглавен ред Origin, като много заявки сървър-към-сървър и инструменти от командния ред. Дали искате това поведение, е решение на политиката на приложението; CORS сам по себе си не е удостоверяване.
Стъпка 4: Проверете простата заявка и всяка предварителна заявка (preflight)
Илюстрация, генерирана от AI, а не реален екранен снимка: проверете дали браузърът получава очаквания CORS заглавен ред и дали всяка предварителна заявка OPTIONS успява.
Презаредете фронтенда и проверете панела Network. Условието за успех не е просто статус 200. Проверете заглавните редове на отговора. В нашия илюстративен случай отговорът на API трябва да включва стойност за произход, еквивалентна на:
Някои заявки между различни произходи задействат предварителна заявка (preflight): браузърът изпраща OPTIONS заявка преди истинската заявка, за да провери дали методът и заглавните редове са разрешени. Заявки, използващи методи като PUT или DELETE, или определени персонализирани/заявни заглавни редове, обикновено изискват preflight. Когато cors е инсталиран като middleware на ниво приложение с app.use(cors(...)), официалната документация на Express казва, че предварителните заявки се обработват за всички маршрути.
Можете също да проверите заглавните редове извън браузъра, без да твърдите, че клиентът от командния ред прилага CORS:
Това е полезно, за да видите какво връща сървърът, но успешна заявка с curl или API клиент не доказва, че CORS в браузъра е конфигуриран правилно. Документацията на Express за CORS изрично отбелязва, че CORS се прилага от браузърите; небраузърни клиенти не прилагат същото ограничение за четене.
Заявки с удостоверяващи данни: не комбинирайте удостоверяващи данни с wildcard произход
Ако фронтендът трябва да изпраща бисквитки или HTTP удостоверяване между различни произходи, и двете страни се нуждаят от съвместими настройки. От страната на Express конфигурирайте конкретен доверен произход и активирайте удостоверяващите данни:
От страната на браузъра, fetch заявка, която има нужда от бисквитки, обикновено използва credentials: 'include'. Не превключвайте произхода на сървъра на * за заявка с удостоверяващи данни. Браузърите не приемат wildcard Access-Control-Allow-Origin заедно с CORS с удостоверяващи данни по начина, по който разработчиците често очакват, а неограниченият произход би бил и слаба граница за сигурност.
Защо честите „решения“ се провалят
Опит
Защо не решава истинския проблем
По-добър подход
Задайте mode: 'no-cors' във fetch
Отговорът става непрозрачен (opaque), така че JavaScript не може да прочете тялото на отговора или повечето заглавни редове.
Конфигурирайте CORS на сървъра, който контролирате.
Тествайте само в Postman или curl
Тези клиенти не прилагат политиката на браузъра за CORS.
Инспектирайте действителните заглавни редове на заявката и отговора в браузъра.
Можете да зададете CORS заглавни редове ръчно с API за отговор на Express, но е лесно да пропуснете поведението при preflight, правилата за удостоверяващи данни, динамичното съвпадение на произхода, Vary: Origin или пътищата при грешка. Официалният cors middleware вече предлага опции за origin, методи, разрешени заглавни редове, изложени заглавни редове, удостоверяващи данни, поведение при preflight и максимална възраст (max age). За повечето Express проекти използването на това middleware държи политиката ясна и по-лесна за преглед.
Ако имплементирате динамична логика за произхода сами, никога не отразявайте автоматично всяка входяща стойност на Origin, само защото е налична. Валидирайте я срещу набор от доверени стойности. MDN предупреждава, че неограничените четения между произходи могат да разкрият данни, особено когато са замесени удостоверяващи данни.
Практически чеклист за производство
Избройте точните произходи на фронтенда, които трябва да могат да четат API.
Използвайте HTTPS произходи в производство и дръжте произходите за разработка отделни.
Инсталирайте CORS middleware преди защитените API маршрути, които имат нужда от него.
Използвайте конкретни произходи за частни или удостоверяващи крайни точки.
Проверете както нормалните отговори, така и отговорите на предварителни заявки OPTIONS в браузъра.
Проверете пътищата при грешка, като отговори 401, 404 и 500, ако те могат да бъдат върнати между различни произходи.
Третирайте CORS като политика за четене на браузъра, а не като удостоверяване или упълномощаване.
В илюстративния сценарий с таблица за задачи, трайното решение е просто: идентифицирайте точния произход на фронтенда, конфигурирайте Express да връща съвпадащия CORS заглавен ред, оставете middleware на ниво приложение да обработи preflight и проверете заглавните редове в отговора, който браузърът всъщност получава. Ако заглавният ред все още липсва след това, следващият заподозрян обикновено е редът на middleware или инфраструктурата между браузъра и Express, а не самата fetch заявка на фронтенда.