GET и POST в веб-формах: как работают и когда какой выбрать

GET и POST в веб-формах: как работают и когда какой выбрать Полезное

GET и POST — это методы протокола HTTP, а не «команды HTML». HTML лишь выбирает метод: в теге <form> за это отвечает атрибут method. GET запрашивает данные и передает параметры в адресной строке, POST отправляет данные на сервер и кладет их в тело запроса. Ниже разберем, чем они отличаются на практике, как выглядят в форме и в запросе, и по каким признакам выбирать метод.

Метод HTTP — это не «команда HTML»

Исходный заголовок статьи неточен: «команд HTML» не существует. HTML — язык разметки, он описывает структуру страницы. GET, POST и другие методы принадлежат протоколу HTTP — по нему браузер (клиент) общается с сервером.

HTML участвует только в одном: форма <form method="..."> говорит браузеру, каким HTTP-методом отправить данные. Сам запрос уходит уже по HTTP.

Кроме GET и POST протокол знает и другие методы — HEAD, PUT, PATCH, DELETE, OPTIONS. Но HTML-форма нативно поддерживает только два значения атрибута method: get и post. Остальные методы отправляют из JavaScript через fetch или из инструментов вроде curl. Поэтому в контексте форм речь всегда о паре GET/POST.

Как работает GET

GET запрашивает содержимое ресурса. Параметры он передает прямо в URL — после знака ? идут пары «имя=значение», соединенные амперсандом &.

Форма с методом GET:

<form action="/search" method="get">
  <input type="text" name="q" value="http">
  <input type="number" name="page" value="2">
  <button type="submit">Найти</button>
</form>

После нажатия «Найти» браузер перейдет по адресу /search?q=http&page=2. Параметры видны в строке адреса, их можно скопировать, сохранить в закладки, переслать.

Тот же запрос через curl (сервис httpbin.org возвращает то, что получил, — удобно для проверки):

curl "https://httpbin.org/get?q=http&page=2"

В ответе видно, что параметры пришли в поле args, а тело запроса пустое.

По спецификации GET — безопасный (safe) и идемпотентный метод. Безопасный означает, что запрос не должен менять состояние на сервере (только читает). Идемпотентный — что повторение запроса дает тот же результат на сервере, что и однократный вызов. Это не про «один и тот же ответ» (данные могут обновиться), а про отсутствие побочных эффектов от повтора.

Из этих свойств следуют практические удобства: ответы на GET кешируются браузерами и прокси, страницы индексируются поисковиками, URL добавляются в закладки и историю.

Как работает POST

POST отправляет данные на сервер и кладет их в тело запроса, а не в URL. В адресной строке параметров не видно.

Форма входа с методом POST:

<form action="/login" method="post">
  <input type="text" name="username">
  <input type="password" name="password">
  <button type="submit">Войти</button>
</form>

Браузер отправит на /login тело вида username=ivan&password=secret. По умолчанию форма кодирует его как application/x-www-form-urlencoded; для загрузки файлов задают enctype="multipart/form-data".

Тот же запрос через curl (флаг -d автоматически делает метод POST и ставит нужный Content-Type):

curl -X POST https://httpbin.org/anything/login \
  -d "username=ivan&password=secret"

В ответе httpbin вернет данные в поле form, а не в args. Обратите внимание: в командной строке все флаги пишутся обычными дефисами (-X, -d), не типографским тире, иначе оболочка их не распознает.

POST — не идемпотентный и не безопасный метод. Повторная отправка может создать дубли: два клика по кнопке «Опубликовать» дадут два комментария. Поэтому ответы на POST по умолчанию не кешируются, а браузер предупреждает при повторной отправке формы (обновление страницы после POST).

Таблица: GET vs POST

Признак GET POST
Где параметры в URL после ? в теле запроса
Видны в адресной строке да нет
Идемпотентный да (по спецификации) нет
Безопасный (только чтение) да нет, меняет состояние
Кешируется да нет (по умолчанию)
В истории и закладках сохраняется не сохраняется
Лимит длины ограничен длиной URL тело практически не ограничено
Файлы нельзя можно (multipart/form-data)
Назначение получить данные отправить или изменить данные

Лимиты длины: у GET они есть, у POST практически нет

Сам стандарт HTTP не задает жесткого предела длины URL. Ограничения ставят браузеры и веб-серверы: исторически ориентир — около 2000 символов, безопасных почти везде, но конкретные версии браузеров и настройки серверов допускают и больше. Точную цифру закладывать в код не стоит — она зависит от окружения.

У POST тело ограничено настройками сервера (например, лимитом на размер запроса), а не длиной адреса. Поэтому большие объемы, длинные тексты и файлы отправляют через POST.

Безопасность: чем POST лучше и чего он не дает

Данные GET уходят в URL, а URL «протекает» в нескольких местах: строка адреса на экране, история браузера, закладки, логи веб-сервера и прокси, заголовок Referer при переходе по ссылке. Все это видит больше глаз, чем нужно.

Отсюда правило: не передавайте пароли, токены и другие секреты через GET. Логин из примера выше должен идти только методом POST, чтобы пароль не осел в истории и логах.

Важная граница, которую часто путают: POST не шифрует данные. Он лишь убирает их из URL, истории и логов доступа. От перехвата в сети (провайдер, публичный Wi-Fi) защищает только HTTPS (TLS) — он шифрует и тело POST, и параметры GET в пути. Правильно так: секреты — через POST и обязательно поверх HTTPS.

И POST не заменяет проверок на сервере: от онлайн-подбора пароля нужны ограничение частоты попыток и блокировки, а не выбор метода запроса.

Когда какой метод выбирать

Ориентируйтесь на характер операции, а не на «удобство»:

  • Запрос читает данные и не меняет состояние (поиск, фильтр, страница каталога) — GET. Результат тогда можно кешировать, дать ссылкой, открыть повторно.
  • Запрос меняет состояние (регистрация, вход, оплата, отправка комментария, загрузка файла) — POST. Так вы избегаете дублей при повторе и не светите данные в URL.
  • Нужно передать секрет или большой объем — POST (плюс HTTPS).
  • Хотите, чтобы результат можно было добавить в закладки или переслать ссылкой — GET.

Простой критерий: «после этого запроса на сервере что-то поменяется?» Если да — POST, если нет — GET.

Выводы

  • GET и POST — методы HTTP, а не «команды HTML»; в форме метод задает атрибут method (только get или post).
  • GET кладет параметры в URL, POST — в тело запроса; отсюда все различия по видимости, лимитам и кешированию.
  • GET безопасный и идемпотентный (только чтение), POST меняет состояние и не идемпотентен — его повтор может создать дубли.
  • Пароли и секреты нельзя слать через GET: URL попадает в историю, закладки и логи; для секретов — POST поверх HTTPS.
  • Правило выбора: читаем данные — GET, меняем состояние — POST.

Где применяется / связь с практикой

Формы, поиск, фильтры и авторизация — это то, с чего начинается любой веб-интерфейс, и метод запроса тут выбирают в первых же строках верстки. Разобравшись, чем GET отличается от POST, вы будете осмысленно ставить method и enctype, а не копировать наугад.

Освойте тему на практике

Если хотите системно освоить верстку и разметку форм, посмотрите курс HTML/CSS. Перед записью можно бесплатно сходить на открытые уроки и посмотреть формат вживую.

FAQ

Можно ли отправить файл через GET?
Нет. Файлы передают только методом POST с enctype="multipart/form-data" — в URL двоичные данные не помещаются.

Виден ли POST в логах сервера так же, как GET?
Обычно нет: серверы логируют строку запроса с URL, а тело POST по умолчанию в лог доступа не пишется. Но от перехвата в сети это не спасает — нужен HTTPS.

Почему форма с method="put" не работает?
HTML-форма нативно поддерживает только get и post; неизвестное значение браузер трактует как GET. Для PUT, PATCH или DELETE используйте fetch из JavaScript.

OTUS Журнал
Бесплатные открытые уроки (поп-ап)