Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Зачем нужен запрос OPTIONS в HTTP?
OPTIONS — это HTTP метод, который используется для получения информации о доступных методах и возможностях коммуникации с ресурсом. Часто используется в контексте CORS (Cross-Origin Resource Sharing).
Основное назначение OPTIONS
OPTIONS запрос позволяет клиенту узнать, какие методы доступны для определённого ресурса, какие заголовки поддерживаются и другие параметры коммуникации.
# Пример обработки OPTIONS в FastAPI
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# CORS уже обрабатывает OPTIONS автоматически
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Но можно обработать OPTIONS вручную
@app.options("/api/users")
async def preflight_users():
return {
"allowed_methods": ["GET", "POST", "OPTIONS"],
"allowed_headers": ["Content-Type", "Authorization"],
"allowed_origins": ["*"],
"max_age": 3600 # Кэшировать результат на 1 час
}
Два основных применения
1. CORS Preflight запрос
Это самое частое использование OPTIONS. Когда браузер делает cross-origin запрос определённого типа, он сначала отправляет OPTIONS запрос (preflight) для проверки прав доступа.
# Браузер на example.com отправляет запрос к api.other.com
# Процесс:
# 1. Браузер отправляет preflight OPTIONS запрос
OPTIONS /api/users HTTP/1.1
Host: api.other.com
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
# 2. Сервер отвечает с разрешениями
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 3600
# 3. Если разрешено, браузер отправляет реальный запрос
POST /api/users HTTP/1.1
Host: api.other.com
Origin: https://example.com
Content-Type: application/json
Пример с Flask:
from flask import Flask, request
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # Автоматически обрабатывает OPTIONS
@app.route('/api/users', methods=['GET', 'POST', 'OPTIONS'])
def users():
if request.method == 'OPTIONS':
response = app.make_default_options_response()
response.headers['Access-Control-Allow-Headers'] = 'Content-Type'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'
return response
elif request.method == 'POST':
# Обработка POST
return {"message": "User created"}
else: # GET
return {"users": []}
2. Получение доступных методов
Клиент может использовать OPTIONS для выяснения, какие методы поддерживает API.
# Запрос
OPTIONS * HTTP/1.1
Host: example.com
# Ответ
HTTP/1.1 200 OK
Allow: GET, HEAD, PUT, DELETE, OPTIONS
Accept-Ranges: bytes
Content-Length: 0
Когда браузер отправляет preflight OPTIONS запрос
Не для каждого запроса браузер отправляет preflight. OPTIONS отправляется только для "non-simple" запросов:
# Простые запросы (БЕЗ preflight):
# - GET, HEAD, POST
# - Стандартные headers: Accept, Accept-Language, Content-Language, Content-Type
# - Content-Type только: application/x-www-form-urlencoded, multipart/form-data, text/plain
# Сложные запросы (С preflight OPTIONS):
# 1. Метод: PUT, DELETE, PATCH
fetch('https://api.example.com/users/1', {
method: 'PUT', # Сложный метод
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name: 'John'})
})
# Браузер отправит OPTIONS перед PUT
# 2. Custom headers
fetch('https://api.example.com/users', {
method: 'GET',
headers: {'X-Custom-Header': 'value'} # Custom header
})
// OPTIONS будет отправлен
# 3. Content-Type: application/json
fetch('https://api.example.com/users', {
method: 'POST',
headers: {'Content-Type': 'application/json'}, # Не simple
body: JSON.stringify({name: 'John'})
})
// OPTIONS будет отправлен
Обработка OPTIONS в разных фреймворках
FastAPI с автоматической CORS
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["https://example.com", "https://app.example.com"],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["*"],
max_age=600, # Кэшировать preflight на 10 минут
)
@app.post("/api/users")
async def create_user(user_data: dict):
return {"id": 1, "name": user_data["name"]}
# OPTIONS обрабатывается автоматически, нет нужды писать обработчик
Django с django-cors-headers
# settings.py
INSTALLED_APPS = [
'corsheaders',
# ...
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
# ...
]
CORS_ALLOWED_ORIGINS = [
"https://example.com",
"https://app.example.com",
]
CORS_ALLOW_METHODS = [
'GET',
'POST',
'PUT',
'DELETE',
]
CORS_ALLOW_HEADERS = [
'Content-Type',
'Authorization',
]
# OPTIONS обрабатывается автоматически
Ручная обработка OPTIONS
from fastapi import FastAPI
app = FastAPI()
@app.options("/api/users/{user_id}")
async def options_user(user_id: int):
return {
"allowed_methods": ["GET", "PUT", "DELETE"],
"allowed_headers": ["Content-Type", "Authorization"],
"allowed_origins": ["*"],
}
@app.get("/api/users/{user_id}")
async def get_user(user_id: int):
return {"id": user_id, "name": "John"}
@app.put("/api/users/{user_id}")
async def update_user(user_id: int, data: dict):
return {"id": user_id, "updated": True}
@app.delete("/api/users/{user_id}")
async def delete_user(user_id: int):
return {"deleted": True}
Оптимизация OPTIONS запросов
1. Кэширование preflight
# Сервер сообщает браузеру кэшировать результат
Access-Control-Max-Age: 86400 # Кэшировать на 24 часа
# Браузер не будет отправлять OPTIONS для каждого запроса
2. Минимизация preflight запросов
# Плохо: 3 preflight запроса
fetch('/api/users', {method: 'POST', headers: {'X-Header': 'value'}})
fetch('/api/products', {method: 'POST', headers: {'X-Header': 'value'}})
fetch('/api/orders', {method: 'POST', headers: {'X-Header': 'value'}})
# Хорошо: используй простые запросы (если возможно)
fetch('/api/users', {method: 'POST', headers: {'Content-Type': 'application/json'}})
3. Используй Access-Control-Max-Age
# Высокое значение = меньше preflight запросов
Access-Control-Max-Age: 86400 # 24 часа
# Низкое значение = чаще проверяется доступ
Access-Control-Max-Age: 300 # 5 минут
Заключение
OPTIONS — это критический метод для CORS. Понимание preflight запросов важно для:
- Отладки проблем с CORS
- Оптимизации производительности
- Безопасности (CORS является механизмом безопасности браузера)
- Проектирования API
В большинстве случаев фреймворки обрабатывают OPTIONS автоматически, но понимание механизма необходимо для опытного разработчика.