HTTP POST 四种常见的提交数据方式

Posted by Yezhiwei on May 21, 2019

背景

今天在与第三方联调接口的时候,发现一些问题:对 HTTP 协议的请求方法使用不合理(本来以为这些对工程师来说已经是常识了),协议规定的 HTTP 请求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 这几种。其中 POST 一般用来向服务端提交数据,也可用来与第三方交互数据。

用 Content-Type : application/json 方式传输数据,json 数据会被框架自动解析为对像并自动给相应的属性设置好值

POST 提交数据

  • HTTP 协议是建立在 TCP/IP 协议之上的应用层规范。规范把 HTTP 请求分为三个部分:状态行、请求头、消息主体。如下:
<method> <request-URL> <version>
<headers>

<entity-body>
  • 协议规定 POST 提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式,只要最后发送的 HTTP 请求满足上面的格式就可以(HTTP 协议是以 ASCII 码传输)。
  • 一般服务端语言如 Java、Python 等,以及它们的 Framework,都内置了自动解析常见数据格式的功能。服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。所以 POST 提交的数据,包含了 Content-Type 编码方式和消息主体两部分。

四种常见的 POST 提交数据方式

application/x-www-form-urlencoded

这个是最常见的 POST 提交数据的方式。form 表单,如果不设置 enctype 属性,那么默认以 application/x-www-form-urlencoded 的方式提交数据。

POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8

title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3

Content-Type 被指定为 application/x-www-form-urlencoded;

提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。

multipart/form-data

常用于表单上传文件时,并且必须让 form 表单的 enctype 等于 multipart/form-data

POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"

title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png

PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

这种方式一般用来上传文件

application/json

application/json 这个 Content-Type 作为响应头用来告诉服务端消息主体是序列化后的 JSON 字符串。

JSON 格式支持比键值对复杂得多的结构化数据,数据的发送请求的格式为:

POST http://www.example.com HTTP/1.1 
Content-Type: application/json;charset=utf-8

{"title":"test","sub":[1,2,3]}

这种方式,可以方便的提交复杂的结构化数据,特别适合 RESTful 的接口。

各大抓包工具如 Chrome 自带的开发者工具、Firebug、Fiddler,都会以树形结构展示 JSON 数据,非常友好。

text/xml

XML 一般用于传输和存储数据,它非常适合提供统一的方法来描述和交换独立于应用程序的结构化数据,在 JSON 出现之前是业界一大标准,因此,在 POST 提交数据时,虽然一般场景上使用 JSON 可能更轻巧、灵活,但 XML 类型也是不可缺少的一种。

XML-RPC 就是利用 XML 编码,使用 HTTP 协议进行传输的一种协议机制,它使用的就是这种编码类型,XML-RPC 协议简单、功能够用,各种语言的实现都有。

// XML-RPC 请求的范例
<?xml version="1.0"?>
<methodCall>
  <methodName>examples.getStateName</methodName>
  <params>
    <param>
        <value><i4>40</i4></value>
    </param>
  </params>
</methodCall>
// 相对于上述请求,以下为一个响应的范例:
<?xml version="1.0"?>
<methodResponse>
  <params>
    <param>
        <value><string>South Dakota</string></value>
    </param>
  </params>
</methodResponse>

参考 XML-RPC in Wikipedia

总结

POST 请求的消息主体放在 entity body 中,服务端根据请求头中的 Content-Type 字段来获取消息主体的编码方式,进而进行解析数据。