在http的规范中有OPTIONS,GET,HEAD,POST,PUT,DELETE,TRACE,CONNECT,那么发送这些类型的请求会在头部携带Content-Type,本文重点讲述与此相关内容,Content-Type属性指定请求和响应的HTTP内容类型,如果未指定Content-Type,默认为text/html(如果想具体查看所有的ContentType,可以查找nginx中的mime.typs),下面就讲述三种主要的Content-Type。

1.application/x-www-form-urlencoded类型

application/x-www-form-urlencoded类型会把表单中发送的数据编码为”名称=值”对,浏览器把form数据封装到http body中,然后发送到服务器,其中用curl请求www.baidu.com对应的header:

POST / HTTP/1.1
Host: www.baidu.com
User-Agent: curl/7.51.0
Accept: */*
Content-Length: 897
Content-Type: application/x-www-form-urlencoded

*******raw body*****

服务端收到的POST中的数据是数组,其中raw body数据如下:

wd=&from=pc_web&rf=3&hisdata=%5B%7B%22time%22%3A1491282408%2C%22
kw%22%3A%22hilo%20%E9%BA%BB%E5%B0%86%22%7D%2C%7B%22time%22%3A149
1282424%2C%22kw%22%3A%22hilo%E5%BC%95%E6%93%8E%20%E9%BA%BB%E5%B0
%86%22%7D%2C%7B%22time%22%3A1491282435%2C%22kw%22%3A%22hilo%E5%B
C%95%E6%93%8E%20%E6%96%97%E5%9C%B0%E4%B8%BB%22%7D%2C%7B%22time%2
2%3A1491282451%2C%22kw%22%3A%22html5%20%E6%96%97%E5%9C%B0%E4%B8%
BB%22%7D%2C%7B%22time%22%3A1491282620%2C%22kw%22%3A%22hilo%E5%BC
%95%E6%93%8E%22%7D%2C%7B%22time%22%3A1491282626%2C%22kw%22%3A%22
hilo%22%2C%22fq%22%3A2%7D%2C%7B%22time%22%3A1491356796%2C%22kw%2
2%3A%22mac%20%E6%9F%A5mac%22%7D%2C%7B%22time%22%3A1491405511%2C%
22kw%22%3A%22the%20definitive%20guide%20to%20sqlite%22%7D%2C%7B%
22time%22%3A1491405600%2C%22kw%22%3A%22memcache%E6%80%A7%E8%83%B
D%22%7D%5D&json=1&p=3&sid=22164_1458_21086_20718&req=2&sc=eb&cso
r=0&cb=jQuery1102039103513342575114_1491813440556&_=149181344055

2.multipart/form-data类型

multipart/form-data用于发送文件数据,同样使用curl发送文件数据到www.baidu.com,命令如下:

curl --trace-ascii test.log 'http://www.baidu.com/' -F'filename=@***'

发送数据的完整请求:

POST / HTTP/1.1
Host: www.baidu.com
User-Agent: curl/7.51.0
Accept: */*
Content-Length: 215
Expect: 100-continue
Content-Type: multipart/form-data; boundary=--------------------
----99ae40e79f72be6d

--------------------------99ae40e79f72be6d
Content-Disposition: form-data; name="filename"; filename="test.
log.1"
Content-Type: application/octet-stream

testdata

--------------------------99ae40e79f72be6d--

从以上的请求数据可以看出Content-Type是multipart/form-data,使用boundary定义的分割符分隔(99ae40e79f72be6d),当文件太长,HTTP无法在一个包之内发送完毕,就需要分割数据,分割成一个一个chunk发送给服务端;
其中Content-Disposition描述文件名(回报文也可以标识下载文件名,如需要浏览器保存可以下发header:Content-Disposition:attachment;filename=***.txt)。

3.text/xml,application/json和text/plain等其他类型

以text/xml的Content-Type为例,请求的header的数据如下:

POST / HTTP/1.1
Host: www.baidu.com
User-Agent: curl/7.51.0
Accept: */*
Content-Type: text/xml
Content-Length: 16

<root>111</root>

从以上请求的数据可以看出,text/xml,application/json和text/plain等数据都是以raw(未经加工的纯文本)的形式发送,只是对于不同的Content-Type填写相应的发送的数据格式,如果php需要取这类型的数据,可以使用$data = file_get_contents(‘php://input’)。

HTTP/1.1 100 Continue

既然说到了文件上传,那么也顺便解释一下:HTTP/1.1 100 Continue,完整的官方解释翻译http的100返回码如下:

使用100(不中断,继续)状态码的目的是为了在客户端发出请求体之前,让服务器根据客户端发出的请求信息(根据请求的头信息)来决定是否愿意接受来自客户端的包含了请求内容的请求;在某些情况下,如果服务器拒绝查看消息主体,这时客户端发送消息主体是不合适的或会降低效率

这个是我在写文件上传nginx交互的数据:

> POST /uploadfile HTTP/1.1
> Host: 139.129.212.166
> User-Agent: curl/7.51.0
> Accept: */*
> Content-Length: 1873
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------6edc99e25765bfea
>
< HTTP/1.1 100 Continue
HTTP/1.1 100 Continue

< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Server: openresty/1.11.2.3
Server: openresty/1.11.2.3
< Date: Sun, 11 Jun 2017 14:04:31 GMT
Date: Sun, 11 Jun 2017 14:04:31 GMT
< Content-Type: text/html
Content-Type: text/html
< Transfer-Encoding: chunked
Transfer-Encoding: chunked
< Connection: keep-alive
Connection: keep-alive

<
http://www.zqsiwei.com/static/upload/1497189871/savefile.html

那么返回100的具体含义是什么呢?
答:在使用curl做POST的时候, 当要POST的数据大于1024字节的时候, curl并不会直接就发起POST请求, 而是会分为俩步:1. 发送一个请求, 包含一个Expect:100-continue, 询问Server使用愿意接受数据,2. 接收到Server返回的100-continue应答以后, 才把数据POST给Server;