HTTP 有两类报文
请求报文——从客户向服务器发送请求报文。(发送哪些请求,如GET获取网页内容。账户名,密码提交给服务器,需要POST)
响应报文——从服务器到客户的回答。(服务器收到请求给客户端一个状态,请求成功或者失败,有没有权限访问)
由于 HTTP 是面向正文的 (text-oriented),因此在报文中的每一个字段都是一些 ASCII 码串,因而每个字段的长度都是不确定的。(明文的,不加密)
HTTP 的报文结构(请求报文)
http报文有两种,一种是请求报文(从请求端发出的),另外一种叫响应报文(从服务器发出的),而里面的信息就是HTTP协议交互的信息。
HTTP 请求报文
HTTP 请求报文由 3 大部分组成:
请求行(必须在 HTTP 请求报文的第一行)
请求头(从第二行开始,到第一个空行结束。请求头和请求体之间存在一个空行)
请求体(通常以键值对 {key:value}方式传递数据)
报文分为三个部分,请求行,请求头,请求体,需要说明一点,请求体是可以忽略的。
比如请求方法header方法,它就不会去获取请求体,而对于请求头来说,它是由多行数据构成的字符串文本,数据都是通过换行符隔开。
请求行开头的 POST 表示请求访问服务器的类型,称为方法(method),随后的字符串 /form/login 指明了请求访问的资源对象,也叫做请求 URI(request-URI)。
最后的 HTTP/1.1 即 HTTP 的版本号,用来提示客户端使用的 HTTP 协议功能。
综上来看,这段请求的意思就是:请求访问某台 HTTP 服务器上的 /form/login 页面资源,并附带参数 name = veal、age = 37。
注意,无论是 HTTP 请求报文还是 HTTP 响应报文,请求头/响应头和请求体/响应体之间都会有一个“空行”,且请求体/响应体并不是必须的。
curl 'https://www.baidu.com/?name=lulei&age=29' \
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' \
-H 'Accept-Language: zh-CN,zh;q=0.9' \
-H 'Connection: keep-alive' \
-H 'Cookie: BIDUPSID=616742439A1B008BD27A12AAF298A29D; PSTM=1650946218; BAIDUID=616742439A1B008BF808E3254C13E17E:FG=1; BDUSS=klxQ3kxdi1jSk1OckJ3eVN3NnBqSjZRZzNGdGJzYTg3a3NMU0w5V1pTd0k5YXBpSVFBQUFBJCQAAAAAAAAAAAEAAAA73A1HY29tcGxpY2F0ZeKZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhog2IIaINiY; BDUSS_BFESS=klxQ3kxdi1jSk1OckJ3eVN3NnBqSjZRZzNGdGJzYTg3a3NMU0w5V1pTd0k5YXBpSVFBQUFBJCQAAAAAAAAAAAEAAAA73A1HY29tcGxpY2F0ZeKZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhog2IIaINiY; BAIDUID_BFESS=616742439A1B008BF808E3254C13E17E:FG=1; BD_UPN=12314753; B64_BOT=1; ZFY=MOsBXemfFniuaZLTJ3073pkaKW75MEjp6dEzxJns6js:C; BD_HOME=1; BA_HECTOR=21840l8h85050gah8h20au1e1hm65iu1b; BDRCVFR[mkUqnUt8juD]=mk3SLVN4HKm; delPer=0; BD_CK_SAM=1; PSINO=3; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; baikeVisitId=2eb7d275-e969-431d-92cb-c479fe62ae2a; COOKIE_SESSION=13_1_5_6_3_5_0_0_5_2_2_1_39_0_0_0_1667353664_1666775331_1667454485%7C9%230_1_1666775322%7C1; H_PS_PSSID=; sugstore=0' \
-H 'Sec-Fetch-Dest: document' \
-H 'Sec-Fetch-Mode: navigate' \
-H 'Sec-Fetch-Site: none' \
-H 'Sec-Fetch-User: ?1' \
-H 'Upgrade-Insecure-Requests: 1' \
-H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36' \
-H 'sec-ch-ua: "Chromium";v="106", "Google Chrome";v="106", "Not;A=Brand";v="99"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "Windows"' \
--compressed
请求行(一)
request-line = method request-target HTTP-version CRLF
请求行定义是Request line,方法+request target+HTTP版本
如同所示GET就是一个方法,中间request target就是这个的path,最后是版本号。
请求行(二)
request-target = origin-form / absolute-form / authority-form / asterisk-form
request-target有四种格式,最常用的格式是origin-form,它是向源服务器,产生响应内容的服务器发起请求的。
在浏览器当中配置了正向代理proxy之后,这个时候使用的request target就采用了absolute-form,就是后面会跟着完整的url。
connect方法,将建立VPN等隧道的时候才会使用到CONNECT www.example.com:80 HTTP/1.1
请求行(三)
HTTP-version 版本号发展历史:https://www.w3.org/Protocols/History.html
常见方法(RFC7231)
• GET:主要的获取信息方法,大量的性能优化都针对该方法,幂等方法(调用一次和调用多次获得的结果是完全一致的)
所以在2007年的时候nginx在0.5版本对trace方法不再支持了,每次发送trace方法都返回405错误码。
-I来查看options方法一个响应的头部。可以看到返回allow头部,新资源支持哪些方法的访问。