Короткий ответ
CORS (Cross-Origin Resource Sharing) — механизм браузера, разрешающий или запрещающий JS-коду с одного origin делать запросы к API на другом origin; браузер блокирует ответ на стороне клиента, если сервер не вернул правильные заголовки Access-Control-Allow-*, даже если сам HTTP-запрос дошёл и обработался успешно.
Как это работает подробнее
для "небезопасных" запросов (например, с кастомными заголовками или методом PUT/DELETE) браузер сначала отправляет предварительный OPTIONS-запрос (preflight), и только если сервер ответит разрешающими заголовками, выполняется основной запрос. Для простых GET/POST без специальных заголовков preflight не нужен, но ответ всё равно будет скрыт от JS без Access-Control-Allow-Origin.
Пример кода
example.py
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["https://frontend.example.com"],
allow_credentials=True,
allow_methods=["GET", "POST", "PATCH", "DELETE"],
allow_headers=["Authorization", "Content-Type"],
)Что использовать на практике
- Рекомендация. сервер должен явно указать разрешённые origin, методы и заголовки;
Access-Control-Allow-Origin: *подходит для публичных API без авторизации через cookie, но несовместим сAccess-Control-Allow-Credentials: true. Настройку обычно делают через middleware фреймворка, а не руками в каждом эндпоинте.
Подводные камни
- Риски. считать CORS защитой самого API от несанкционированных запросов (на самом деле это защита браузерного пользователя, серверные-к-серверным запросам CORS не мешает); ставить
Access-Control-Allow-Origin: *вместе с передачей cookie/credentials, что браузер прямо запретит; забывать обрабатывать методOPTIONSна сервере, из-за чего preflight возвращает 404/405.