基础 - 请求报文结构介绍 ¶
作者:KK
发表日期:2017.9.7
POST请求体样本 ¶
建议你先通过《Fiddler - 基础抓包》学会如何抓取一个HTTP请求的信息
一个常见的HTTPGET请求
的内容如下:
POST http://www.kkh86.com/http-test.do HTTP/1.1
Host: www.kkh86.com
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 15
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.3368.400 QQBrowser/9.6.11974.400
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
Cookie: auto-login=1
name=Jay&age=33
第一部分:请求行 ¶
第一行GET http://www.kkh86.com/http-test.do HTTP/1.1
就叫做请求行
,这行内容又分为以下三个元素:
请求方法
前面第一个词表示了本次HTTP请求的方法(GET、POST、PUT、DELETE、HEAD、OPTIONS、TRACE、CONNECT)
请求地址
这个请求地址是带有host的,就算HTML里只写了“href="/http-test.do"”,但浏览器会自动跟当前网页的域名拼接成完整的地址构成这个HTTP请求信息,比如“http://www.kkh86.com/http-test.do”
在非浏览器的请求场景中,比如通过PHP的curl函数发起请求,又或是Java、C#等代码,都必须写入完整网址,不然你只写相对路径的话人家怎么知道往哪个host发送请求呢
协议版本
HTTP1.1
表示本次通讯数据格式的书写排版是遵循HTTP的1.1版本协议的,HTTP最初的版本是1.0,但没多久就升级为1.1了,至少目前我还没见过哪个软件还使用1.0版本协议来通讯我虽然看地几次1.1和1.0的具体区别,但其实多年来发现知道这些区别对我们日常开发来说没任何作用,而最后我也背不出来,建议你不要去关心这些版本区别吧,因为我可以说的就是当今能在我们各种系统中使用的浏览器都使用1.1版本与服务器通讯,你学了1.0的东西也不知往哪用
这个版本可以说是万年不变的,1.0因为某些缺陷被废弃了,1.1正在流行,无论你用什么抓包、浏览器抓包都是看到这个版本号,会看腻的
在未来5~10年等HTTP2.0版本普及后就能在抓包过程中发现1.1和2.0两个版本号了
第二部分:请求头 ¶
下面这堆东西就是请求头,它们都是Key: value
的结构,也就是只有2个元素(:
号隔开),与请求行的三个元素数量都不同,很容易辨识
Host: www.kkh86.com
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 15
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.3368.400 QQBrowser/9.6.11974.400
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
Cookie: auto-login=1
其中Host就是请求的目标主机地址
User-Agent是请求客户端的代理头,用我的话来说就是“描述了客户端的一个字符串”
其它Connection、Accept什么的你不用太关心,看多了就熟悉它们了,通常在服务端写业务代码的时候不需要关心这些请求头,服务器的通讯层会分析并处理它们
最后那个Cookie当然就是浏览器的Cookie啦,只要Cookie还没过期,每次请求都会附在请求头里,当Cookie多了的时候就会很占带宽了,后面《注意Cookie》再专门讲这个
可以追加自定义请求头 ¶
请参考JS版代码演示《前端进阶 - 少用但偶尔会碰到 - ajax自定义header》
服务端要接收这些请求头的时候,以我熟悉的PHP语言为例,可以从$_SERVER数组取到这个自定义请求头的值:$myHeader1 = $_SERVER['HTTP_MYHEAD1'];
(全部自动转换成大写,前面加个HTTP前缀说明是通过HTTP协议请求发送过来的信息)
第三部分:请求体 ¶
name=Jay&age=33
请求信息底下这个就是请求体,我们可以理解为“请求的附加数据”,甚至不严格地说是请求参数,它与请求头之间会有一个空行
,这点很重要
你可以发现这些内容就是UrlEncode格式,没错,GET请求把UrlEncode参数放在请求地址上,而POST请求就是把参数以UrlEncode的方式放在请求体里面,只是放的位置不同,但二者的格式是默认一致的
可以自定义请求体格式 ¶
如果在浏览器里用form标签加submit按钮提交的话,浏览器会自动将参数组装成UrlEncode格式,包括在jquery里如果这样传入一个key value对象也会自动转换成UrlEncode:
$.post('/xx.do', {
name : 'Jay',
age : 11
});
$.ajax({
url : '/xx.do',
data : {
name : 'Jay',
age : 11
}
});
都会变成name=Jay&age=11
放到请求体里面
要自定义格式的话只能通过ajax请求来发送:
$.ajax({
url : '/xx.do',
data : JSON.stringify({
name : 'Jay',
age : 11
})
});
这样构造的请求报文大概如下(主要是最后一行,请求体不是UrlEncode而是JSON):
POST http://kk/xx.do HTTP/1.1
Host: kk
Connection: keep-alive
Content-Length: 23
Pragma: no-cache
Cache-Control: no-cache
Origin: http://kk
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.3368.400 QQBrowser/9.6.11974.400
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: */*
Referer: http://kk/it/index.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
{"name":"Jay","age":11}
每种编程语言都有默认的接收参数格式,大部分是UrlEncode格式,如果你某天调试的时候发现收不到参数,请抓包看看参数的格式是怎样的,如果是JSON或XML什么的,那就要另外换一个参数的读取方式了
比如PHP语言,是不能直接通过$_POST['name']
这样来取值的,在《PHP进阶 - curl - 发送GET/POST请求》里我讲解了发送JSON数据的时候如何接收
GET方法不会有请求体 ¶
GET的请求报文是这样的:
GET http://www.kkh86.com/it/demo/js/check-all.html HTTP/1.1
Host: www.kkh86.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.3368.400 QQBrowser/9.6.11974.400
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
第一行是请求行,下面全是请求头,然后就没有然后了,你多看几个抓包记录就熟悉了