> Какие бывают виды HTTP-запросов и их семантика (Go)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: Моторика

Стек: Go

> Пример ответа

Короткий ответ

Основные HTTP-методы: GET - получение ресурса без побочных эффектов, POST - создание ресурса или выполнение действия с побочными эффектами, PUT - полная замена ресурса по известному URI, PATCH - частичное обновление, DELETE - удаление. Также есть HEAD (как GET, но без тела), OPTIONS - запрос поддерживаемых методов и CORS preflight, CONNECT - туннель, TRACE - диагностика. Семантика определяется RFC 9110, но на практике важны идемпотентность и безопасность: GET, HEAD, OPTIONS, TRACE безопасны; PUT, DELETE идемпотентны; POST и PATCH - нет.

Подробное объяснение

Семантика методов определяется двумя ключевыми свойствами: безопасность (safe) - метод не изменяет состояние сервера, и идемпотентность (idempotent) - повторное выполнение даёт тот же результат, что и первое.

  • GET - безопасный и идемпотентный. Используется для чтения. Кэшируется, может быть условным (If-None-Match, If-Modified-Since).
  • HEAD - идентичен GET, но сервер не возвращает тело. Используется для проверки существования ресурса, получения метаданных, проверки заголовков.
  • POST - не безопасный, не идемпотентный. Создание ресурса, отправка данных на обработку, выполнение действий. Ответ - 201 Created с Location, либо 200/204.
  • PUT - идемпотентный, не безопасный. Полная замена ресурса по известному URI. Если ресурса нет - создаёт (201), если есть - заменяет (200/204). Повторный PUT с теми же данными не меняет состояние.
  • PATCH - не идемпотентный, не безопасный. Частичное обновление. Отличие от PUT: PUT заменяет весь ресурс, PATCH применяет частичные изменения (например, JSON Patch или Merge Patch).
  • DELETE - идемпотентный, не безопасный. Удаление ресурса. Повторный DELETE возвращает 404, но состояние сервера не меняется - поэтому идемпотентен.
  • OPTIONS - безопасный. Запрос поддерживаемых методов для ресурса, используется в CORS preflight. Ответ содержит Allow header.
  • CONNECT - устанавливает туннель (например, для HTTPS через прокси). Редко используется в прикладном коде.
  • TRACE - диагностический, возвращает запрос как его получил сервер. Часто отключается из соображений безопасности (XST-атаки).

Важные нюансы:

  • Семантика - это контракт, но реализация может отличаться. Например, POST может быть идемпотентным на практике, но это не гарантируется.
  • HTTP-методы не привязаны к CRUD жёстко: PUT может создавать, POST - обновлять, если это соответствует контракту API.
  • Кэширование по умолчанию применяется только к GET и HEAD, если не указано иное.
  • В Go стандартный пакет net/http обрабатывает методы через r.Method, но для REST-роутинга обычно используют chi, gin или echo.

На практике

В реальных API выбор метода - это проектирование контракта. Основные практические правила:

  • Для чтения - всегда GET, даже если нужно передать сложный фильтр (используй query parameters, не тело запроса).
  • Для создания - POST, если клиент не знает итоговый URI. Если клиент задаёт URI - PUT.
  • Для обновления - PUT для полной замены, PATCH для частичной. PATCH сложнее: нужно определить формат (JSON Merge Patch - RFC 7386, JSON Patch - RFC 6902).
  • Для удаления - DELETE.
  • Для операций, которые не вписываются в CRUD (например, "отправить письмо", "запустить задачу") - POST на действие: POST /users/{id}/send-verification.
  • Идемпотентность критична для повторных попыток: если клиент не получил ответ из-за таймаута, он может безопасно повторить PUT/DELETE, но не POST. Для POST можно использовать Idempotency-Key header (как в Stripe).
  • Обработка ошибок: 405 Method Not Allowed + Allow header, если метод не поддерживается.
  • В Go middleware для логирования, авторизации и rate limiting должен учитывать метод - например, не логировать тело GET, не требовать CSRF-токен для безопасных методов.

Пример кода

GO
// Обработка методов в net/http
func handler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
// чтение
case http.MethodPost:
// создание
case http.MethodPut:
// полная замена
case http.MethodPatch:
// частичное обновление
case http.MethodDelete:
// удаление
default:
w.Header().Set("Allow", "GET, POST, PUT, PATCH, DELETE")
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
}
// Идемпотентный PUT: повторный запрос не меняет состояние
func putHandler(w http.ResponseWriter, r *http.Request) {
var data Resource
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
http.Error(w, "bad request", http.StatusBadRequest)
return
}
// Полная замена: сохраняем data как есть, без слияния
err := repo.Replace(r.PathValue("id"), data)
if err != nil {
http.Error(w, "internal error", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
// PATCH с JSON Merge Patch (RFC 7386)
func patchHandler(w http.ResponseWriter, r *http.Request) {
var patch map[string]interface{}
if err := json.NewDecoder(r.Body).Decode(&patch); err != nil {
http.Error(w, "bad request", http.StatusBadRequest)
return
}
current, err := repo.Get(r.PathValue("id"))
if err != nil {
http.Error(w, "not found", http.StatusNotFound)
return
}
// Применяем merge patch: null удаляет поле
merged := mergePatch(current, patch)
repo.Save(r.PathValue("id"), merged)
w.WriteHeader(http.StatusOK)
}

Как отвечать на собеседовании

Начни с перечисления методов и их базовой семантики. Затем переходи к ключевым свойствам - безопасность и идемпотентность, приведи примеры, почему POST не идемпотентен, а PUT идемпотентен. Покажи понимание различий между PUT и PATCH - это частый вопрос. Упомяни практические нюансы: кэширование, CORS preflight, Allow header, Idempotency-Key. Если спросят про нестандартные методы - расскажи про CONNECT и TRACE, но отметь, что они редко используются в прикладных API. Заверши примером из своего опыта: как выбирал метод для конкретной операции и какие trade-off учитывал.

Что проверяет интервьюер

  • Понимание не просто списка методов, а их семантики: безопасность и идемпотентность.
  • Умение объяснить разницу между PUT и PATCH, POST и PUT.
  • Знание практических аспектов: кэширование, CORS, обработка ошибок, повторные запросы.
  • Способность применить знания к проектированию API: какой метод выбрать для конкретной операции.
  • Понимание ограничений: семантика - это контракт, а не жёсткое правило.

Типичные ошибки

  • Путаница между PUT и PATCH: говорят, что PUT - это "обновление", не уточняя, что полное.
  • Утверждение, что POST всегда создаёт ресурс - на самом деле POST может выполнять любые действия.
  • Игнорирование идемпотентности: не понимают, почему повторный DELETE не проблема, а повторный POST - проблема.
  • Забывают про HEAD и OPTIONS, хотя они важны для мониторинга и CORS.
  • Говорят, что GET не может иметь тело запроса - формально может, но это плохая практика и многие серверы игнорируют его.
  • Не упоминают Allow header в ответе 405.
  • Путают безопасность и идемпотентность: безопасный метод всегда идемпотентен, но идемпотентный не всегда безопасен (PUT, DELETE).

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью