Ответ
OPTIONS — это один из стандартных HTTP-методов, который используется для описания параметров и возможностей взаимодействия с целевым ресурсом (URL).
Клиент может использовать OPTIONS для запроса информации о том, какие методы (GET, POST, PUT и т.д.) и заголовки поддерживаются сервером для данного ресурса, не инициируя при этом никаких действий с самим ресурсом.
Основное применение — CORS Preflight Request (предварительный запрос)
Это самый частый сценарий использования OPTIONS. Браузер автоматически отправляет OPTIONS-запрос перед "сложными" кросс-доменными запросами, чтобы проверить, разрешает ли сервер такой запрос.
"Сложным" запрос считается, если он:
- Использует методы, отличные от
GET,POST,HEAD. - Содержит заголовки, отличные от стандартных (например,
Authorization,X-Custom-Header). - Имеет
Content-Type, отличный отapplication/x-www-form-urlencoded,multipart/form-dataилиtext/plain.
Как это работает:
- Браузер хочет отправить
PUTзапрос с заголовкомAuthorizationс сайтаA.comна APIB.com/resource. - Перед отправкой
PUT, браузер автоматически посылаетOPTIONSзапрос наB.com/resource. - Сервер
B.comдолжен ответить наOPTIONSзапрос, указав в заголовках ответа, что он разрешает методPUTи заголовокAuthorizationс доменаA.com(например, черезAccess-Control-Allow-Methods: PUTиAccess-Control-Allow-Headers: Authorization). - Если ответ на
OPTIONSположительный, браузер отправляет основнойPUTзапрос.
Пример обработки в Go (net/http):
func handler(w http.ResponseWriter, r *http.Request) {
// Устанавливаем общие заголовки для всех ответов
w.Header().Set("Access-Control-Allow-Origin", "*") // В проде лучше указать конкретный домен
// Обработка предварительного запроса
if r.Method == http.MethodOptions {
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
w.WriteHeader(http.StatusNoContent) // 204 No Content - стандарт для успешного preflight
return
}
// Обработка основного запроса (GET, POST и т.д.)
w.Write([]byte("Hello, world!"))
}
Примечание: В реальных приложениях для обработки CORS обычно используют готовые middleware-библиотеки (например,
gorilla/handlers,rs/corsили встроенные в фреймворки вроде Gin/Echo), которые делают эту логику более надежной и простой в настройке.
Ответ 18+ 🔞
Ну слушай, вот есть у нас в HTTP такая штука — метод OPTIONS. Это как бы предварительный звонок, типа «эй, сервак, а можно я тебе вот так вот приеду?». Сука, просто представь: ты хочешь отправить запрос с одного сайта на другой, а браузер, этот перестраховщик ебаный, сначала стучится OPTIONS-ом, чтобы проверить, не наебешь ли ты ему всю систему.
Зачем это вообще нужно?
В основном, блядь, для CORS — этих самых кросс-доменных запросов. Браузер, падла такая, сам отправляет OPTIONS перед тем, как сделать «сложный» запрос. А сложный — это если ты лезешь не с GET или простеньким POST, а, например, с PUT, да ещё и с каким-нибудь своим хитрожопым заголовком вроде Authorization. Или Content-Type у тебя не text/plain, а какой-нибудь application/json. Короче, любое отклонение от стандартного сценария — и вот тебе, на, получай предварительный запрос.
Как это выглядит на практике:
- Твой фронт на
frontend.comхочет отправитьDELETEзапрос с заголовкомX-API-Keyнаapi.backend.com/data. - Браузер, блядь, не дурак, он сначала шлёт
OPTIONSзапрос на тот же адрес: «Э, api.backend.com, а можно я тебе пришлюDELETEи заголовокX-API-Key?». - Сервер должен ответить: «Да, хуле, можно. Вот тебе заголовки
Access-Control-Allow-Methods: DELETEиAccess-Control-Allow-Headers: X-API-Key. И заходи, родной, сfrontend.com». - Только после этого, довольный браузер отправляет уже настоящий, основной
DELETEзапрос. А если сервер в ответ наOPTIONSнакосячил — всё, пиши пропало, запрос не уйдёт, будет тебе в консоли красненькое.
Вот как это может выглядеть на Go, если писать в лоб:
func handler(w http.ResponseWriter, r *http.Request) {
// Сразу говорим, откуда можно приходить (в проде "*" — это пиздец как небезопасно, указывай конкретный домен)
w.Header().Set("Access-Control-Allow-Origin", "*")
// Ловим этот самый предварительный запрос
if r.Method == http.MethodOptions {
// Разрешаем методы
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
// Разрешаем заголовки
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, X-API-Key, Authorization")
// Статус 204 — всё ок, но тела ответа нет
w.WriteHeader(http.StatusNoContent)
return
}
// А тут уже обрабатываем нормальные запросы (GET, POST и т.д.)
w.Write([]byte("Всё работает, епта!"))
}
Важный момент, нахуй: В нормальных, боевых проектах никто эту хуйню вручную не прописывает. Берут готовые middleware — типа
rs/corsдля чистогоnet/httpили встроенные средства в Gin/Echo. Они всё за тебя сделают, а то сам накосячишь с заголовками и потом будешь ебаться, почему запросы не летят.