> Какие бывают виды 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/httpfunc 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 Resourceif 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).
> Похожие задачи по backend
Как пользоваться программой top в Linux
Какие виды уведомлений используются в системах (SMS, push, email и т.д.)
Что такое конкурентность в программировании
Кто ставит задачи и как они распределяются
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью