Привет! Если ты разрабатываешь API, которое будет использоваться из браузера, рано или поздно столкнёшься с CORS. Это механизм безопасности, который ограничивает запросы с других доменов.
В этой статье мы разберём:
- Что такое CORS
- Зачем он нужен
- Как настроить CORS в FastAPI
- Параметры CORSMiddleware
- Практические примеры
- Что нужно знать перед началом
- Основная часть
- Что такое CORS
- Установка CORS в FastAPI
- Настройка CORS
- Разрешённые домены (allow_origins)
- Разрешённые методы (allow_methods)
- Разрешённые заголовки (allow_headers)
- Разрешённые credentials (allow_credentials)
- Полный пример CORS
- CORS с использованием переменных окружения
- Предзапрос (Preflight Request)
- CORS и аутентификация
- Обработка ошибок CORS
- Задачи для закрепления
- Нюансы и подводные камни
- allow_origins=["*"] и allow_credentials=True несовместимы
- CORS и preflight запросы
- CORS в продакшене
- CORS и локальная разработка
- Частые ошибки и как их избежать
- Ошибка 1: allow_origins=["*"] с allow_credentials=True
- Ошибка 2: Забыл указать метод OPTIONS
- Ошибка 3: Неправильный порт в разрешённых доменах
- Шпаргалка
- Заключение
- КВИЗ
- Что дальше?
Что нужно знать перед началом
Для этого урока тебе понадобится:
- Установленный FastAPI
- Базовое понимание HTTP-запросов
Совет: CORS — это не баг, а защита. Браузеры блокируют запросы с других доменов по умолчанию для безопасности.
Основная часть
Что такое CORS
CORS (Cross-Origin Resource Sharing) — это механизм, который позволяет серверу разрешать или запрещать запросы с других доменов.
Пример проблемы:
# Ваше API: https://api.example.com
# Ваш фронтенд: https://frontend.example.com
# Запрос из фронтенда блокируется браузером!CORS-заголовки:
Access-Control-Allow-Origin: https://frontend.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization, Content-TypeСовет: Без CORS браузер блокирует запросы с других доменов. Настройка CORS нужна, чтобы разрешить их.
Установка CORS в FastAPI
FastAPI предоставляет встроенный CORSMiddleware из Starlette.
pip install fastapi[all] # или просто fastapiИмпорт и использование:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Разрешает все домены
allow_credentials=True,
allow_methods=["*"], # Разрешает все методы
allow_headers=["*"], # Разрешает все заголовки
)
@app.get("/")
async def root():
return {"message": "Hello, World!"}Важно:
allow_origins=["*"]разрешает доступ с любых доменов. В продакшене так делать небезопасно.
Настройка CORS
Разрешённые домены (allow_origins)
# Конкретные домены
app.add_middleware(
CORSMiddleware,
allow_origins=[
"https://myfrontend.com",
"https://app.myfrontend.com",
"http://localhost:3000", # Для разработки
],
)Разрешённые методы (allow_methods)
# Только GET и POST
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["GET", "POST"],
)Разрешённые заголовки (allow_headers)
# Только определённые заголовки
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_headers=["Authorization", "Content-Type"],
)Разрешённые credentials (allow_credentials)
# Разрешить отправку cookies и токенов
app.add_middleware(
CORSMiddleware,
allow_origins=["https://myfrontend.com"],
allow_credentials=True, # Разрешает отправку credentials
)Важно: Если
allow_credentials=True,allow_originsне может быть["*"]. Нужно указывать конкретные домены.
Полный пример CORS
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# Настройка CORS
origins = [
"https://myfrontend.com",
"https://app.myfrontend.com",
"http://localhost:3000",
"http://localhost:8080",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["Authorization", "Content-Type", "Accept"],
expose_headers=["X-Custom-Header"], # Доступные клиенту заголовки
max_age=600, # Время кеширования CORS-запроса (в секундах)
)
@app.get("/")
async def root():
return {"message": "CORS настроен!"}CORS с использованием переменных окружения
import os
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# Получаем разрешённые домены из переменной окружения
origins = os.getenv("ALLOWED_ORIGINS", "").split(",")
# Если переменная не установлена — разрешаем localhost для разработки
if not origins or origins == [""]:
origins = ["http://localhost:3000", "http://localhost:8000"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)Совет: В продакшене указывай разрешённые домены через переменные окружения, чтобы безопасно управлять ими.
Предзапрос (Preflight Request)
Когда браузер отправляет небезопасный запрос (не GET, не с простыми заголовками), он сначала отправляет preflight запрос (OPTIONS).
# Preflight запрос (OPTIONS)
# Проверяет, разрешён ли основной запрос
# Основной запрос (POST)
# Отправляется только после успешного preflightCORSMiddleware автоматически обрабатывает preflight запросы.
CORS и аутентификация
Если ты используешь JWT или cookies, нужно разрешить allow_credentials.
app.add_middleware(
CORSMiddleware,
allow_origins=["https://myfrontend.com"],
allow_credentials=True, # Разрешить cookies
allow_methods=["*"],
allow_headers=["Authorization", "Content-Type"],
)На клиенте (JavaScript):
fetch("https://api.example.com/users", {
credentials: "include", # Важно! Отправляет cookies
headers: {
"Authorization": "Bearer " + token,
"Content-Type": "application/json",
}
})Совет: Не забывай про
credentials: "include"на фронтенде.
Обработка ошибок CORS
Если CORS настроен неправильно, браузер выдаст ошибку:
Access to fetch at 'https://api.example.com/users' from origin 'https://myfrontend.com' has been blocked by CORS policyКак исправить:
- Проверь, что
allow_originsсодержит домен фронтенда. - Проверь, что
allow_methodsсодержит нужный метод. - Проверь, что
allow_headersсодержит нужные заголовки. - Если используешь
allow_credentials=True, убедись, чтоallow_origins— не["*"].
Задачи для закрепления
Задача 1. Настрой CORS для одного домена.
Задача 2. Настрой CORS для нескольких доменов.
Задача 3. Разреши только GET и POST методы.
Задача 4. Разреши отправку cookies.
Задача 5. Настрой CORS через переменные окружения.
Ответы:
Задача 1.
app.add_middleware(
CORSMiddleware,
allow_origins=["https://myfrontend.com"],
allow_methods=["*"],
allow_headers=["*"],
)Задача 2.
app.add_middleware(
CORSMiddleware,
allow_origins=["https://frontend1.com", "https://frontend2.com"],
allow_methods=["*"],
allow_headers=["*"],
)Задача 3.
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["GET", "POST"],
allow_headers=["*"],
)Задача 4.
app.add_middleware(
CORSMiddleware,
allow_origins=["https://myfrontend.com"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)Задача 5.
import os
origins = os.getenv("ALLOWED_ORIGINS", "http://localhost:3000").split(",")
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_methods=["*"],
allow_headers=["*"],
)Нюансы и подводные камни
allow_origins=["*"] и allow_credentials=True несовместимы
Если нужно отправлять cookies или авторизационные заголовки, указывай конкретные домены.
CORS и preflight запросы
Preflight запросы могут замедлять работу API. Используй max_age для кеширования.
CORS в продакшене
Никогда не используй allow_origins=["*"] в продакшене. Указывай конкретные домены.
CORS и локальная разработка
Добавь http://localhost:3000 и http://127.0.0.1:3000 в список разрешённых для разработки.
Частые ошибки и как их избежать
Ошибка 1: allow_origins=["*"] с allow_credentials=True
Неправильно:
allow_origins=["*"],
allow_credentials=TrueПравильно:
allow_origins=["https://myfrontend.com"],
allow_credentials=TrueОшибка 2: Забыл указать метод OPTIONS
CORSMiddleware автоматически добавляет OPTIONS.
Ошибка 3: Неправильный порт в разрешённых доменах
Указывай точный порт, если он отличается от 80/443.
Шпаргалка
| Параметр | Назначение |
|---|---|
allow_origins | Разрешённые домены |
allow_methods | Разрешённые методы HTTP |
allow_headers | Разрешённые заголовки |
allow_credentials | Разрешить cookies и авторизацию |
expose_headers | Заголовки, доступные клиенту |
max_age | Время кеширования preflight |
Заключение
Сегодня мы:
- Узнали, что такое CORS
- Настроили CORS в FastAPI
- Разобрали параметры CORSMiddleware
- Практические примеры








