0x00 背景

POST是在平日中很常见一种请求方式。相比于GET请求方式来说,POST更加的安全(不会被保存在浏览器历史或WEB服务器日志中)也支持更大的数据传输(GET请求因为是在URL添加参数所以受到URL长度的限制,即只支持2048个字符)。

通过POST提交的数据是需要放在请求头的消息体中,支持的格式主要有下面四种,而对于这四种的识别则是服务器端对请求头的content-tyep参数来进行判断的。

0x01 multipart/form-data

multipart/form-data 是新增的编码类型,以提高二进制文件的传输效率。这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。 某表单的源代码如下:

 



<form action="upload.php" enctype="multipart/form-data" method="post">
<input name="myflie" type="file" />
<input type="submit" />



当在该表单输入内容进行提交的时候就会产生一个POST请求,其中的Content-Type参数值就会被设置为multipart/form-data

同时还会因为其特殊的格式增加一个boundary参数,这个参数是一个分隔符,分隔多个文件、表单项,他的值要足够的复杂或者随机,以保证不会与上传表单或者文件的内容出现重复。

请求头部分内容如下:



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--



可以看到消息体被boundary分隔开了,整个消息体以 --boundary开始,各个表单的内容使用--boundary分隔开,最后使用--boundary--来结束

0x02 application/x-www-form-urlencoded

这是最常见的POST提交数据的方法了吧。在源代码未知道enctype的时候默认就使用这种方式来提交。请求头类似于这样:



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



可以看到消息体中提交的内容使用&进行连接,同时使用了URL编码,所以就像是把GET请求的参数放到消息体中一样。大部分服务端语言都对这种方式有很好的支持。很多时候,我们用 Ajax 提交数据时,也是使用这种方式。例如 JQuery 和 QWrap 的 Ajax,Content-Type 默认值都是「application/x-www-form-urlencoded;charset=utf-8」。 

0x03 application/json

由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。同时json可以支持比普通的键值对更加复杂的数据,因此越来越多的人开始使用这种方式进行数据传输。



POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8
 
{"title":"test","sub":[1,2,3]}



0x04 补充

除了以上的3种情况之外,还有一些特殊的content-type。