POST
Применение
Запрос POST отправляет сущность указанному ресурсу. Сервер сам определяет, как обработать вложенное представление, исходя из собственной семантики ресурса. В отличие от PUT, который адресован конкретному URI ресурса, POST делегирует обработку ресурсу, определяемому целевым URI.
Заголовок Content-Type указывает формат тела запроса. В HTML-формах и API распространены три кодировки.
application/x-www-form-urlencoded
Кодировка по умолчанию для HTML-форм. Данные оформляются как пары «ключ-значение», разделённые амперсандами (&), а ключ и значение соединяются знаком равенства (=). Для символов, отличных от букв и цифр, применяется процентное кодирование.
name=Alice&role=admin
multipart/form-data
Каждое поле занимает отдельную часть, отделённую граничной строкой, объявленной в заголовке Content-Type. Эта кодировка поддерживает двоичные данные, например загрузку файлов. Заголовок Content-Disposition внутри каждой части задаёт имя поля.
text/plain
Структура не предписана. Сервер обрабатывает необработанное тело по собственной логике.
Повторные запросы POST не идемпотентны. Двукратная отправка одной и той же формы создаёт два ресурса или дважды запускает обработку, в отличие от PUT, где повторный запрос приводит к тому же состоянию сервера.
Ответы на POST кэшируются только тогда, когда ответ содержит явную информацию о свежести и соответствующий заголовок Content-Location.
Отправка формы
Клиент отправляет данные формы в URL-кодированном виде. Сервер создаёт задачу и отвечает 201 Created.
Запрос
POST /jobs HTTP/1.1
Host: api.example.re
Content-Type: application/x-www-form-urlencoded
Content-Length: 17
name=backup&pri=2
Ответ
HTTP/1.1 201 Created
Location: /jobs/47
Content-Type: application/json
Content-Length: 38
{"id":47,"name":"backup","priority":2}
Загрузка файла через multipart
Клиент загружает файл с использованием multipart-кодировки. Граничная строка ----Boundary разделяет части. Сервер принимает загрузку и возвращает 202 Accepted.
Запрос
POST /uploads HTTP/1.1
Host: api.example.re
Content-Type: multipart/form-data; boundary=----Boundary
Content-Length: 196
------Boundary
Content-Disposition: form-data; name="title"
Q4 Report
------Boundary
Content-Disposition: form-data; name="file"; filename="report.pdf"
Content-Type: application/pdf
<binary data>
------Boundary--
Ответ
HTTP/1.1 202 Accepted
Location: /uploads/91
Content-Length: 0
JSON API
Клиент отправляет полезную нагрузку в формате JSON, чтобы создать нового пользователя. Сервер возвращает созданный ресурс с полем id.
Запрос
POST /users HTTP/1.1
Host: api.example.re
Content-Type: application/json
Content-Length: 41
{"email":"alice@example.re","role":"ops"}
Ответ
HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 50
{"id":112,"email":"alice@example.re","role":"ops"}
CORS
POST входит в белый список методов CORS, но только когда Content-Type равен application/x-www-form-urlencoded, multipart/form-data или text/plain. POST с application/json или любым другим типом содержимого вызывает предварительный запрос OPTIONS.
POST и GET
POST передаёт данные в теле запроса, а не в URL. Благодаря этому параметры не попадают в историю браузера, журналы сервера и заголовки Referer, что делает POST более подходящим для конфиденциальных данных.
Ответы на POST по умолчанию не кэшируются и не добавляются в закладки. POST не является ни безопасным, ни идемпотентным, поэтому повторные отправки создают дублирующиеся ресурсы или запускают обработку несколько раз.
У POST практически нет ограничения на размер тела, тогда как GET ограничен длиной URL примерно в 2048 символов.
Cookie с SameSite=Lax блокируют межсайтовые запросы POST, но разрешают межсайтовые GET. Это даёт POST определённую встроенную защиту от CSRF, которой лишён GET.
Безопасность
Данные POST не появляются в URL, истории браузера или заголовках Referer. По сравнению с GET это снижает риск случайного раскрытия данных.
POST всё равно уязвим для CSRF-атак без надлежащих токенов. Формы на вредоносных страницах автоматически отправляют запросы POST к другим источникам. Cookie с SameSite=Lax обеспечивают частичную защиту, блокируя передачу cookie при межсайтовых POST, но отдельные CSRF-токены по-прежнему необходимы.
POST по обычному HTTP передаёт данные открытым текстом. Для защиты тела запроса при передаче требуется HTTPS.
POST и PATCH
POST создаёт новые ресурсы по URI, выбранным сервером. PATCH изменяет существующие ресурсы по известным URI.
POST полностью делегирует семантику обработки серверу. У PATCH есть определённые форматы патчей, такие как JSON Patch и JSON Merge Patch, которые описывают конкретные изменения для применения.
Когда клиенту нужно обновить отдельные поля существующего ресурса, подходящим методом является PATCH. POST предназначен для создания новых ресурсов или запуска обработки на стороне сервера.