Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

CORS

Браузер защищает посетителей: скрипт со страницы одного сайта не может просто так прочитать ответ другого. Сайт определяется источником (origin) — схемой, доменом и портом. CORS (Cross-Origin Resource Sharing) — правила, по которым сервер сообщает браузеру, каким чужим источникам можно читать его ответы.

Когда это нужно

Допустим, фронтенд блога на React работает на http://localhost:5173, а API — на http://localhost:3000. Порты разные, значит, и источники разные. Скрипт фронтенда делает запрос:

// src/main.js (фронтенд)
const response = await fetch('http://localhost:3000/api/posts');
const posts = await response.json();
console.log(posts);

Сервер ответит, но браузер не отдаст ответ скрипту, а напишет в консоли ошибку со словами blocked by CORS policy. Запрос из curl или с другого сервера при этом работает: CORS проверяет только браузер.

Установка

npm install cors

Разрешаем один источник

Подключите middleware в src/app.js для адресов API:

// src/app.js
import cors from 'cors';
 
app.use('/api', cors({ origin: 'http://localhost:5173' }));

Middleware добавит к ответам заголовок Access-Control-Allow-Origin: http://localhost:5173. Обновите страницу фронтенда — в консоли появится массив статей.

Несколько источников

В origin можно передать массив — например, адрес для разработки и рабочий домен:

// src/app.js
app.use('/api', cors({
  origin: ['http://localhost:5173', 'https://example.com'],
  methods: ['GET', 'POST', 'PATCH', 'DELETE'],
}));

Запросы с других сайтов браузер по-прежнему заблокирует.

Предварительный запрос

Перед «непростыми» запросами — например, DELETE или POST с JSON и заголовком Authorization — браузер сначала сам отправляет запрос методом OPTIONS. Он спрашивает сервер, разрешён ли такой запрос. Middleware cors отвечает на него сама, если подключена через app.use(): дополнительный код писать не нужно.

Заголовок ответаЧто разрешает
Access-Control-Allow-OriginЧитать ответ указанному источнику
Access-Control-Allow-MethodsИспользовать перечисленные методы
Access-Control-Allow-HeadersОтправлять перечисленные заголовки
Access-Control-Allow-CredentialsОтправлять cookie

Если фронтенд должен отправлять cookie сессии, нужны две вещи: опция credentials: true в cors() на сервере и credentials: 'include' в fetch() на клиенте. С токеном JWT в заголовке Authorization этого не требуется.

Частая ошибка

Вызов cors() без опций разрешает запросы с любого сайта. Для открытого API только для чтения это допустимо, но для адресов, которые меняют данные, — нет. Всегда перечисляйте свои источники в origin. И помните: CORS не заменяет авторизацию — он ограничивает только браузеры, а программы могут обратиться к API напрямую.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.