Когда браузер через форму или ссылку, например, или программа отправляет данные на сервер, это делается с помощью HTTP-запросов. Самые распространённые из них — GET и POST. Они выполняют похожие задачи (передают данные), но делают это по-разному. Это методы RESTful API, кроме которых существуют еще PUT и DELETE. Однако использование GET и POST намного больше. Давайте рассмотрим, в чем же заключается разница между этими двумя методами и их применением.
Метод GET — “получить данные”
Метод, или запрос GET используют, когда нужно просто запросить информацию у сервера. Например, когда вы открываете сайт или страницу с поисковыми результатами, делаете вы это с помощью метода GET.
Данные передаются в адресной строке. Например: https://somesite.com/search?query=laptop или https://somesite.com/products?category=phones. В данных примерах данными являются ?query=laptop или ?category=phones, в зависимости от которых страница будет сформирована иначе, чем при отсутствии этих данных в запросе.
Что мы можем увидеть в GET-запросе?
- Эти данные видны пользователю и могут быть сохранены в истории браузера.
- GET-запрос можно добавить в закладки или поделиться ссылкой, потому что все нужные данные в ней уже есть.
- Он не должен менять данные на сервере, только получать их.
- Есть ограничение по длине — слишком много данных передать не получится.
С помощью GET-запроса мы можем получить данные путем использования Fetch API. Сделаем это с помощью сайта JSONPlaceholder. Это бесплатный учебный API, где можно тренироваться с запросами без риска “сломать” настоящий сайт.
| 1 2 3 4 5 6 7 8 9 10 11 | <ul class="test" id="usersList"> </ul> <script> fetch('https://jsonplaceholder.typicode.com/users') .then(response => response.json()) .then(data => { console.log('Список пользователей:', data); //вы увидите в консоли массив объектов data.forEach(item => usersList.innerHTML += `<li>${item.name}</li>`) }) .catch(error => console.error('Ошибка:', error)); </script> |
Результат - список пользователей.
Метод POST — “отправить данные”
Метод POST используют, когда нужно отправить что-то на сервер — например, форму регистрации, заказ, сообщение и т.п. В этом случае данные передаются в теле запроса, а не в адресной строке, т.е. увидеть и прочитать или скопировать их не удастся.
Например:
| 1 2 3 4 | POST /login HTTP/1.1 Content-Type: application/x-www-form-urlencoded username=admin&password=12345789 |
Особенности POST-запроса
- Пользователь не видит отправленные данные, они не сохраняются в истории браузера.
- Можно передавать любое количество данных, в том числе файлы.
- Чаще всего POST-запрос изменяет что-то на сервере (создаёт запись, отправляет сообщение и т. д.)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <div class="test" id="postInfo"></div> <script> fetch('https://jsonplaceholder.typicode.com/posts', { method: 'POST', // тип запроса headers: { 'Content-Type': 'application/json; charset=UTF-8', }, body: JSON.stringify({ title: 'Мой первый пост', body: 'Пример отправки данных через POST-запрос.', userId: 1 }) }) .then(response => response.json()) .then(data => { console.log('Ответ от сервера:', data); for(let prop in data){ postInfo.innerHTML+= `<p><b>${prop}:</b> ${data[prop]}</p>`; } }) .catch(error => console.error('Ошибка:', error)); </script> |
Ниже вы увидите результат ответа с сервера.
Есть еще ряд моментов, или вопросов, которые стоит рассмотреть в плане понимания разницы между GET и POST запросами.
GET или POST?
- Параметры какого метода сохраняются в истории сеанса браузера?
- Какой метод можно кэшировать на стороне браузера?
- Какой метод является «безопасным»?
- Какой метод используется в статический веб-сайтах?
- Какой метод имеет ограничения по длине?
- Какой метод допускает только символы ASCII?
- Какой метод следует использовать для работы с конфиденциальными данными??
- Какой метод можно добавить в закладки?
Давайте разберем эти два метода более подробно и разберемся в их особенностях.
1. Параметры GET будут сохранены в истории сеанса браузера
Браузер использует свою историю для навигации пользователя назад и вперед, следовательно, каждый новый введенный URL будет автоматически попадать в историю. Но что, если запрос GET выполняется неявно через SPA (например, через AJAX, Fetch API или Axios)? В этом случае URL запроса должен быть отправлен вручную через history.pushState, и он может быть обновлен на URL-адресе браузера без перенаправления пользователя.
Рассмотрим 2 разных сценария:
A. Перейдите на https://rozetka.com.ua/ua/notebooks/c80004/ и нажмите на любой фильтр (например, HP или Lenovo). Веб-сайт сделает новый запрос GET, получит ответ, повторно отобразит список продуктов, обновит адрес URL браузера и сохранит URL в истории браузера (вы увидите активную стрелку влево/кнопка «Назад»). Хотя страница не была обновлена, новый запрос все равно был отправлен в историю браузера, поэтому вы сможете вернуться на исходную страницу.
URL-адрес в браузере теперь отличается от указанного вначале (https://rozetka.com.ua/ua/notebooks/c80004/producer=lenovo/).
B. Если мы опять откроем в новой вкладке страницу выбора ноутбуков https://rozetka.com.ua/ua/notebooks/c80004/ и вместо того, чтобы нажать на любой фильтр, прокрутим страницу вниз и нажмем «Показати ще», то ситуация изменится. Веб-сайт сделает новый запрос GET, получит ответ, отобразит еще один список продуктов, удлиняя страницу, но НЕ обновит URL-адрес браузера. Плюс кнопка "Назад" останется неактивной, т.е. начальный вид страницы не сохранится в истории браузера. Таким образом, вы НЕ сможете вернуться на исходную страницу.
Что касается POST, если пользователь возвращается назад после отправки формы, данные будут повторно отправлены (браузер должен предупредить пользователя о том, что данные будут повторно отправлены с помощью всплывающего окна), но они не будут сохранены в истории.
2. Кэширование ответов GET-запросов
Поскольку GET является идемпотентным и большинство ресурсов веб-страницы возвращается через этот метод, браузер по умолчанию кэширует get-запросы. Поэтому в следующий раз, когда вы посетите веб-страницу, вместо того, чтобы идти на сервер и запрашивать все изображения снова, она просто загрузит их из кэша браузера.
Когда выполнение нескольких идентичных запросов имеет тот же эффект, что и выполнение одного запроса, REST API называется идемпотентным.
Иными словами идемпотентность по сути означает, что эффект успешно выполненного запроса на ресурс сервера не зависит от количества его выполнений. Например, в арифметике добавление нуля к числу является идемпотентной операцией.
Преимущество этого в том, что ваш сайт будет загружаться намного быстрее после первого раза, т.к. изображения, стили и js-код подтягиваются не с сервера, а из кэша браузера. Однако есть и минусы - новые изменения в стилях, например, не смогут достичь клиента, если в его браузере старый вариант сайта находится в кэше.
В этом случае надо либо обновлять страницу с очисткой кэша (нажатием клавиш CTRL + F5) или очищать кэш через настройки браузера. Есть и другой способ - поменять URL для каждого обновленного запроса. Скажем, если CSS вашего сайта представлен в виде URL http://somesite.com/css/style.css, новый CSS-файл подтянется, только если этот URL будет изменен на что-то вроде http://somesite.com/css/style-24092025120345.css. Например, вы можете добавить в название css-файла метку времени с помощью php-функции filemtime().
А вот метод POST не может быть кэширован на стороне клиента, так как POST не является идемпотентным.
3. Get — безопасный метод
Поскольку метод GET НИКОГДА не должен изменять ресурс (если это происходит, вы не реализуете лучшие практики RESTful), он считается безопасным.
Безопасные методы — это HTTP-методы, которые не изменяют ресурсы.
В результате его можно безопасно кэшировать, сохранять в истории браузера и сохранять в поисковых системах, таких как Google. Это связано с тем, что параметры будут сохранены в URL, и повторный вызов метода не вызовет никаких изменений на сервере.
С другой стороны, POST не является безопасным методом, так как по своей сути он предназначен для изменения некоей информации.
4. Статические веб-сайты отвечают только на запросы GET
Статический сайт — это сайт, где страницы были созданы, как обычные файлы (HTML, CSS, JS, картинки). Когда вы открываете страницу, сервер просто отдаёт готовый файл, не обрабатывая данные и не обращаясь к базе данных.
Примеры:
- Лендинги (например, визитка, портфолио, сайт компании);
- Документации (типа GitHub Pages);
- Сайты, созданные через генераторы вроде Hugo, Jekyll или Astro.
Поэтому статические сайты обычно отвечают только на GET-запросы. POST-запросы не будут обработаны, т.к. на статическом нет инструментов/кода, которые бы могли изменять данные на основе такого запроса. Исключение - обработка отправки форм, но для этого, как правило, подключают сторонний сервис.
5. Какой метод имеет ограничения по длине?
Очень важно понимать, что метод GET всегда будет преобразован в URL в браузере (протокол http), и разрешены в нем только символы ASCII . Другими словами, любой текст, который вы вставите в URL-адрес браузера, будет выполнять запрос типа GET и, даже если запрос GET выполняется неявно через веб-сайт (например, через ajax), он все равно преобразует его в формат URL с параметрами, как в строке запроса.
Зная, что запрос GET в браузере отправит параметры через URL, что, по-вашему, произойдет, если фильтров будет слишком много? Хотя это число может немного отличаться в разных браузерах, безопасный предел длины URL часто составляет 2048 символов, за вычетом количества символов в фактическом пути. В результате, если вы создаете веб-сайт, на котором ваш продукт может иметь большое количество фильтров, метода GET может быть недостаточно.
Практические ограничения длины GET-запроса в браузерах (примерно)
| Среда / программа | Максимальная длина URL |
|---|---|
| Internet Explorer (старые версии) | ~2 083 символа |
| Google Chrome | около 2 048–8 192 символов |
| Firefox | до 65 536 символов |
| Safari | примерно 80 000 символов |
| Opera | около 4 000 символов |
| Apache (сервер) | по умолчанию 8 192 символа |
| Nginx (сервер) | по умолчанию 4 096 символов |
Что касается POST-запроса, поскольку полезная нагрузка отправляется в теле запроса, технически нет ограничений на отправляемые данные и ограничений на тип данных. Практически могут быть ограничения на размер загружаемых данных (файлов, картинок), передаваемых через форму.
6. Какой метод допускает только символы ASCII?
Только метод GET (и вообще URL в целом) допускает только символы ASCII. Если в адресе встречаются другие символы (например, кириллица, пробелы, эмодзи), они должны быть закодированы с помощью URL-кодирования (percent-encoding).
Например, запрос вида https://somesite.com/search?q=яблоко реально в строке адреса выглядит так: https://somesite.com /search?q=%D1%8F%D0%B1%D0%BB%D0%BE%D0%BA%D0%BE .
Это потому что протокол HTTP и URL (Uniform Resource Locator) исторически основаны на ASCII, а не на Unicode. Сеть “понимает” только байты, а не буквы с диакритиками.
Разрешённые ASCII-символы в URL
| Категория | Символы |
|---|---|
| Буквы | A–Z, a–z |
| Цифры | 0–9 |
| Безопасные знаки | -, _, ., ~ |
| Зарезервированные (используются в структуре URL) | :, /, ?, #, [, ], @, !, $, &, ', (, ), *, +, ,, ;, = |
Можно привести такие примеры URL-кодирования:
| Исходная строка | Закодированная версия | Пояснение |
|---|---|---|
яблоко | %D1%8F%D0%B1%D0%BB%D0%BE%D0%BA%D0%BE | Кириллица кодируется UTF-8 → потом в ASCII |
| моя страница | moya%20stranica | Пробел заменён на %20 |
café | caf%C3%A9 | é → %C3%A9 |
POST-запрос не ограничен ASCII, потому что данные передаются в теле запроса, и там можно указать любой Content-Type, например:
Content-Type: application/json; charset=UTF-8
Значит, POST может свободно содержать Unicode (включая кириллицу, китайские и т.д.).
7. Какой метод следует использовать для работы с конфиденциальными данными?
На самом деле ответ вытекает из предыдущего вопроса. Если метод GET дает возможность передавать в строке адреса довольно много символов, то почему бы не использовать его? НО: вы рискнете передавать таким образом имя пользователя и его пароль? Надеюсь, что вы ответили НЕТ.
И это верно, т.к. эти данные должны передаваться POST, а не GET-запросом. Прежде всего, это связано с безопасностью, но не только потому, что информация скрыта. Это также связано с одним из предыдущих пунктов: кэширование и история браузера.
Представьте, что вы начинаете вводить веб-сайт в своем браузере, и он автоматически предлагает URL с именем пользователя и паролем как часть строки запроса. Это может показаться странным, но конечная точка входа GET допускает это, однако, это не то, что вам нужно.
8. Какой метод можно добавить в закладки?
POST не следует добавлять в закладки, и причины этого являются комбинацией нескольких тем, обсуждавшихся выше:
- Попытка добавить POST в закладки приведет только к операции GET на URL.
- Метод не является идемпотентным, поэтому нет гарантии, что ответ всегда будет одинаковым. Например, это может привести к дублированию банковской транзакции.
- URL потеряет свои параметры, так как закладка не поддерживает полезную нагрузку тела.
- Он может содержать конфиденциальные данные, которые не следует сохранять.
Заключение
Итак, пройдемся еще раз по особенностям GET- и POST-запросов.
Особенности GET-запросов:
- GET-запросы можно кэшировать
- GET-запросы сохраняются в истории браузера
- GET-запросы можно добавлять в закладки
- Запросы GET никогда не следует использовать при работе с конфиденциальными данными.
- Запросы GET имеют ограничения по длине
- GET-запросы используются только для запроса данных (не для изменения)
Особенности POST-запросов:
- Запросы POST никогда не кэшируются
- Запросы POST не сохраняются в истории браузера
- Запросы POST не могут быть добавлены в закладки
- Запросы POST не имеют ограничений по длине данных.