Какие ограничения налагает спецификация HTTP на метод GET?

«Какие ограничения налагает спецификация HTTP на метод GET?» — вопрос из категории Сети, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Метод GET в HTTP/1.1 определен RFC 7231 и имеет несколько ключевых ограничений, связанных с его семантикой и безопасностью.

1. Семантическое ограничение: «Безопасность» (Safe)

  • Правило: GET запросы должны быть идемпотентными и безопасными. Это означает, что они не должны изменять состояние сервера.
  • Почему: Позволяет кешированию, индексации поисковыми системами, безопасной перезагрузке страницы в браузере.
  • Нарушение (антипаттерн):
    GET /users/delete?id=123 HTTP/1.1

    Удаление через GET — грубое нарушение контракта метода.

2. Ограничение на передачу данных

  • Правило: Данные передаются только в URL (как query-параметры или часть пути). У запроса нет тела (entity-body).
  • Следствие:
    • Ограничение длины: Максимальная длина URL определяется браузером (обычно ~2000 символов) и сервером (настраивается, например, в nginx large_client_header_buffers).
    • Видимость данных: Параметры видны в истории браузера, логах, referrer.
    • Типы данных: Сложно передавать структурированные данные (например, JSON).

3. Кешируемость (Cacheable)

  • Правило: Ответы на GET запросы по умолчанию считаются кешируемыми.
  • Следствие: Это ограничение для разработчика — если ответ не должен кешироваться, необходимо явно использовать заголовки Cache-Control: no-store.

4. Идемпотентность

  • Правило: Многократное выполнение одного и того же GET запроса должно давать одинаковый результат (при условии, что состояние ресурса на сервере не менялось другими способами).

Практический пример сравнения GET и POST:

// GET: Для получения данных. Параметры в URL.
GET /api/search?query=spring&limit=10 HTTP/1.1
Host: example.com

// POST: Для отправки данных на создание/обработку. Параметры в теле.
POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json

{"name": "John", "email": "john@example.com"}

Вывод: Используйте GET только для операций чтения (получения представлений ресурсов). Для любых действий, изменяющих данные (создание, обновление, удаление), используйте POST, PUT, PATCH или DELETE.