CORS не просто дурацкая настройка, которая заставила вас три раза перечитывать документацию. Это попытка защитить пользователей от злых хакеров, которые хотят отправлять запросы от вашего имени на чужие сайты. Но когда всё настроено неправильно, браузер безжалостно швыряет вам в лицо сообщение: Access to fetch at ... has been blocked by CORS policy. И это только начало забавы.
Спойлер: Если вы нервничаете при виде "CORS Errors" в консоли браузера, это нормально. Сегодня мы научимся не просто понимать эти ошибки, но и чинить их.
Типичные ошибки CORS и их причины
- Ошибка: The 'Access-Control-Allow-Origin' header is missing.
Расшифровка ошибки: браузер не смог найти заголовок, который разрешает выполнение кросс-доменных запросов.- Почему она возникает?
- Вы забыли включить CORS в вашем FastAPI-приложении.
- Неправильная конфигурация источников (например, список разрешённых доменов оставили пустым, а браузер требует точного совпадения источника).
- Пример:
Access to XMLHttpRequest at 'http://api.example.com' from origin 'http://frontend.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. - Почему она возникает?
- Ошибка: CORS preflight channel did not succeed.
Расшифровка ошибки: Preflight-запрос вернул ошибку, до реального выполнения метода (например, POST или DELETE).- Почему она возникает?
- Сервер не разрешает метод OPTIONS, который используется для preflight-запроса.
- В ответе сервера отсутствуют необходимые заголовки (
Access-Control-Allow-Methods,Access-Control-Allow-Headers).
- Почему она возникает?
- Ошибка: The value of the 'Access-Control-Allow-Origin' header must not be the wildcard ('*') when the request's credentials mode is 'include'.
Расшифровка ошибки: сервер отвечает с заголовкомAccess-Control-Allow-Origin: *(разрешает все источники), но клиентский запрос содержит "креденшелы" (cookies, HTTP-авторизация).- Почему она возникает?
- Вы пытаетесь работать с кросс-доменными cookies, но разрешили доступ только всем (
*), а не конкретному источнику.
- Вы пытаетесь работать с кросс-доменными cookies, но разрешили доступ только всем (
- Почему она возникает?
- Ошибка: Response to preflight request doesn't pass access control check.
Расшифровка ошибки: сервер отверг preflight-запрос, так как он не соответствует настройкам CORS.- Почему она возникает?
- Сервер не настроен на обработку необходимых заголовков или методов.
- Клиентский запрос содержит нестандартные заголовки (например,
Authorization), которые не включены в настройку CORS.
- Почему она возникает?
Диагностика ошибок CORS
Когда дело касается CORS, браузеры специально делают процесс менее ясным: они скрывают тело запроса и ответа при ошибке CORS. Поэтому вот ваш план действий:
- Используйте DevTools в браузере
- Откройте вкладку Network в DevTools вашего браузера.
- Найдите проблемный запрос.
- Проверьте заголовки запроса и ответа.
Всё, что вам нужно: присутствие заголовка
Access-Control-Allow-Originв ответе сервера. Если его нет — сервер не разрешает кросс-доменные запросы. - Проверьте preflight-запрос.
Если запрос не проходит, убедитесь, что сервер:- Разрешает метод
OPTIONS(он обязателен для preflight-запросов). - Возвращает заголовок
Access-Control-Allow-Methods, который включает ваши HTTP-методы (GET,POST, и т. д.). - Обрабатывает все обязательные заголовки через
Access-Control-Allow-Headers.
- Разрешает метод
- Двойная проверка клиента и сервера.
- На клиенте проверьте заголовок
Origin— он должен указывать правильный домен. - На сервере убедитесь, что список разрешённых источников (
origins) корректно настроен.
- На клиенте проверьте заголовок
Исправление ошибок CORS в FastAPI
Теперь к делу. Вот как избавиться от упомянутых ошибок.
1. Базовая настройка CORS
Если вы забыли о CORS вообще, начать стоит с включения его в проекте.
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# Разрешённые источники
origins = [
"http://localhost",
"http://localhost:3000", # Для фронтенда на React
"https://myawesomeapp.com" # Ваш продакшн-домен
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins, # Разрешённые источники
allow_credentials=True, # Для работы с cookies
allow_methods=["*"], # Разрешённые методы
allow_headers=["*"], # Разрешённые заголовки
)
2. Настройка preflight-запросов
Для устранения ошибки preflight проверьте, что вы явно разрешаете метод OPTIONS:
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_methods=["GET", "POST", "OPTIONS"], # Убедитесь, что OPTIONS разрешён
allow_headers=["Content-Type", "Authorization"], # Включите специфичные заголовки
)
3. Решение проблемы с wildcard и credentials
Если вы работаете с cookies, нельзя использовать *. Вместо этого укажите конкретный источник.
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"], # Указываем конкретный домен
allow_credentials=True # Включаем работу с cookies
)
4. Отладка нестандартных заголовков
Добавьте все нестандартные заголовки в список разрешённых:
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_headers=["Authorization", "Content-Type", "X-Custom-Header"]
)
Советы по отладке CORS
- Включите логирование запросов и ответов (например, с помощью
logging). - Проверьте, работает ли ваш сервер с HTTPS (для production). Некоторые браузеры блокируют кросс-доменные запросы без HTTPS.
- Если ошибки возникают только на frontend, попробуйте временно отключить CORS (например, с помощью расширений браузера). Это поможет подтвердить, что проблема на стороне сервера.
Практика показывает, что ошибка CORS — это чаще всего проблема конфигурации. Запомните: чем проще и конкретнее ваша настройка (без общего *), тем меньше шанс сломать всё остальное.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ