HTTPQUERY
English

POST

用法

POST 请求向指定资源提交一个实体。服务器根据资源自身的语义来决定如何处理所附带的表示。与针对特定资源 URI 的 PUT 不同,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 不同——重复的 PUT 请求产生相同的服务器状态。

只有当响应包含明确的新鲜度信息以及匹配的 Content-Location 请求头时,POST 响应才可缓存。

表单提交

客户端使用 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":"developer@github.com","role":"ops"}

响应

HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 50

{"id":112,"email":"developer@github.com","role":"ops"}

CORS

POST 是 CORS 安全列表方法,但仅当 Content-Type 为 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 时才成立。使用 application/json 或其他任何内容类型的 POST 都会触发预检 OPTIONS 请求。

POST 与 GET 对比

POST 在请求体而非 URL 中携带数据。这使参数不会出现在浏览器历史记录、服务器日志和 Referer 请求头中,从而使 POST 更适合处理敏感数据。

POST 响应默认不被缓存,也不可加入书签。POST 既不安全也不幂等,因此重复提交会创建重复的资源或多次触发处理。

POST 没有实际的请求体大小限制,而 GET 则受制于约 2048 个字符的 URL 长度限制。

设置了 SameSite=Lax 的 Cookie 会阻止跨站 POST 请求,但允许跨站 GET。这为 POST 提供了 GET 所缺乏的一定程度的内置 CSRF 防护。

安全

POST 数据不会出现在 URL、浏览器历史记录或 Referer 请求头中。与 GET 相比,这降低了意外泄露数据的风险。

在没有适当令牌保护的情况下,POST 仍然容易受到 CSRF 攻击。恶意页面上的表单会自动向其他源提交 POST 请求。SameSite=Lax 的 Cookie 通过阻止跨站 POST 时携带 Cookie 提供了部分防护,但专门的 CSRF 令牌仍然是必需的。

通过普通 HTTP 传输的 POST 会以明文形式传送数据。必须使用 HTTPS 来保护传输中的请求体。

POST 与 PATCH 对比

POST 在服务器选定的 URI 处创建新资源。PATCH 修改已知 URI 处的现有资源。

POST 将处理语义完全委托给服务器。PATCH 具有已定义的补丁格式,例如 JSON Patch 和 JSON Merge Patch,用于描述要应用的具体修改。

当客户端需要更新现有资源上的特定字段时,PATCH 是合适的方法。POST 则用于创建新资源或触发服务器端处理。