HTTP 请求 (request)、响应(response) 请求响应格式

HTTP 消息是服务器和客户端之间交换数据的方式。有两种类型的消息:

  • 请求(request)——由客户端发送用来触发一个服务器上的动作
  • 响应(response)——来自服务器的应答。

HTTP 消息由采用 ASCII 编码的多行文本构成。在 HTTP/1.1 及早期版本中,这些消息通过连接公开地发送。在 HTTP/2 中,为了优化和性能方面的改进,曾经可人工阅读的消息被分到多个 HTTP 帧中。

Web 开发人员或网站管理员,很少自己手工创建这些原始的 HTTP 消息:由软件、浏览器、代理或服务器完成。他们通过配置文件(用于代理服务器或服务器),API(用于浏览器)或其他接口提供 HTTP 消息。

From a user-, script-, or server- generated event, an HTTP/1.x msg is generated, and if HTTP/2 is in use, it is binary framed into an HTTP/2 stream, then sent.

HTTP/2 二进制框架机制被设计为不需要改动任何 API 或配置文件即可应用:它大体上对用户是透明的。

HTTP 请求和响应具有相似的结构,由以下部分组成:

  1. 一行起始行用于描述要执行的请求,或者是对应的状态,成功或失败。这个起始行总是单行的。
  2. 一个可选的 HTTP 标头集合指明请求描述消息主体(body)。
  3. 一个空行指示所有关于请求的元数据已经发送完毕。
  4. 一个可选的包含请求相关数据的主体(比如 HTML 表单内容),或者响应相关的文档。主体的大小有起始行的 HTTP 头来指定。

起始行和 HTTP 消息中的 HTTP 头统称为请求头,而其有效负载被称为消息主体。

Requests and responses share a common structure in HTTP

HTTP 有两类报文


请求报文——从客户向服务器发送请求报文。(发送哪些请求,如GET获取网页内容。账户名,密码提交给服务器,需要POST)

响应报文——从服务器到客户的回答。(服务器收到请求给客户端一个状态,请求成功或者失败,有没有权限访问)

由于 HTTP 是面向正文的 (text-oriented),因此在报文中的每一个字段都是一些 ASCII 码串,因而每个字段的长度都是不确定的。(明文的,不加密)

HTTP请求


起始行

HTTP 请求是由客户端发出的消息,用来使服务器执行动作。起始行(start-line)包含三个元素:

  1. 一个 HTTP 方法,一个动词(像 GETPUT 或者 POST或者一个名词(像 HEAD 或者 OPTIONS),描述要执行的动作。例如,GET 表示要获取资源,POST 表示向服务器推送数据(创建或修改资源,或者产生要返回的临时文件)。
  2. 请求目标(request target),通常是一个 URL,或者是协议、端口和域名的绝对路径,通常以请求的环境为特征。请求的格式因不同的 HTTP 方法而异。它可以是:
    • 一个绝对路径,末尾跟上一个 '?' 和查询字符串。这是最常见的形式,称为原始形式(origin form),被 GETPOSTHEAD 和 OPTIONS 方法所使用。
      • POST / HTTP/1.1
      • GET /background.png HTTP/1.0
      • HEAD /test.html?query=lucas HTTP/1.1
      • OPTIONS /anypage.html HTTP/1.0
    • 一个完整的 URL,被称为绝对形式(absolute form),主要在使用 GET 方法连接到代理时使用。GET http://developer.mozilla.org/zh-CN/docs/Web/HTTP/Messages HTTP/1.1
    • 由域名和可选端口(以 ':' 为前缀)组成的 URL 的 authority 部分,称为 authority form。仅在使用 CONNECT 建立 HTTP 隧道时才使用。CONNECT developer.mozilla.org:80 HTTP/1.1
    • 星号形式(asterisk form),一个简单的星号('*'),配合 OPTIONS 方法使用,代表整个服务器。OPTIONS * HTTP/1.1
  3. HTTP 版本(HTTP version),定义了剩余消息的结构,作为对期望的响应版本的指示符。

标头(Header)

来自请求的 HTTP 标头遵循和 HTTP 标头相同的基本结构:不区分大小写的字符串,紧跟着的冒号(':')和一个结构取决于标头的值。整个标头(包括值)由一行组成,这一行可以相当长。

有许多请求标头可用,它们可以分为几组:

主体 (Body)

请求的最后一部分是它的主体。不是所有的请求都有一个主体:例如获取资源的请求,像 GETHEADDELETE 和 OPTIONS,通常它们不需要主体。有些请求将数据发送到服务器以便更新数据:常见的情况是 POST 请求(包含 HTML 表单数据)。

主体大致可分为两类:

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,最后是版本号。

method 方法:指明操作目的,动词
• request-target = origin-form / absolute-form / authority-form / asterisk-form

请求行(二)


request-target = origin-form / absolute-form / authority-form / asterisk-form

origin-form = absolute-path [ "?" query ]
         • 向 origin server 发起的请求,path 为空时必须传递 /

request-target有四种格式,最常用的格式是origin-form,它是向源服务器,产生响应内容的服务器发起请求的。

absolute-form = absolute-URI
         • 仅用于向正向代理 proxy 发起请求时,详见正向代理与隧道

在浏览器当中配置了正向代理proxy之后,这个时候使用的request target就采用了absolute-form,就是后面会跟着完整的url。

authority-form = authority
         • 仅用于 CONNECT 方法,例如 CONNECT www.example.com:80 HTTP/1.1

connect方法,将建立VPN等隧道的时候才会使用到CONNECT www.example.com:80 HTTP/1.1

asterisk-form = "*“
         • 仅用于 OPTIONS 方法

请求行(三)


HTTP-version 版本号发展历史:https://www.w3.org/Protocols/History.html

HTTP/0.9:只支持 GET 方法,过时
HTTP/ 1.0:RFC1945,1996, 常见使用于代理服务器(例如 Nginx 默认配置,nginx在向上游发起连接的时候,默认还是在使用1.0的协议)
HTTP/ 1.1:RFC2616,1999(对1.0做了改进,支持缓存,支持长连接,对于域名的支持通过host头部
HTTP/ 2.0:2015.5 正式发布

常见方法(RFC7231)


• GET:主要的获取信息方法,大量的性能优化都针对该方法,幂等方法(调用一次和调用多次获得的结果是完全一致的)

HEAD:类似 GET 方法,但服务器不发送响应BODY,用以获取响应HEAD 元数据,幂等方法
POST:常用于提交 HTML FORM 表单、新增资源等(它不是幂等的,提交多次,所得到的结果是完全不同的)
PUT:更新资源,带条件时是幂等方法
DELETE:删除资源,幂等方法
CONNECT:建立 tunnel 隧道
OPTIONS:显示服务器对访问资源支持的方法,幂等方法
TRACE:回显服务器收到的请求,用于定位问题。有安全风险
Changes with nginx 0.5.17 02 Apr 2007 *) Change: now nginx always returns the 405 status for the TRACE method

所以在2007年的时候nginx在0.5版本对trace方法不再支持了,每次发送trace方法都返回405错误码。

-I来查看options方法一个响应的头部。可以看到返回allow头部,新资源支持哪些方法的访问。

 HTTP  响应


状态行

HTTP 响应的起始行被称作状态行(status line),包含以下信息:

  1. 协议版本,通常为 HTTP/1.1
  2. 状态码(status code),表明请求是成功或失败。常见的状态码是 200404 或 302
  3. 状态文本(status text)。一个简短的,纯粹的信息,通过状态码的文本描述,帮助人们理解该 HTTP 消息。

一个典型的状态行看起来像这样:HTTP/1.1 404 Not Found

标头(header)

响应的 HTTP 标头遵循和任何其他标头相同的结构:不区分大小写的字符串,紧跟着的冒号(':')和一个结构取决于标头类型的值。整个标头(包括其值)表现为单行形式。

许多不同的标头可能会出现在响应中。这些可以分为几组:

主体 (Body)

响应的最后一部分是主体。不是所有的响应都有主体:具有状态码(如 201 或 204)的响应,通常不会有主体。

主体大致可分为三类:

  • 单资源(Single-resource)主体,由已知长度的单个文件组成。该类型主体由两个标头定义:Content-Type 和 Content-Length
  • 单资源(Single-resource)主体,由未知长度的单个文件组成。通过将 Transfer-Encoding 设置为 chunked 来使用分块编码。
  • 多资源(Multiple-resource)主体,由多部分 body 组成,每部分包含不同的信息段。但这是比较少见的。

HTTP/2帧

HTTP/1.x 消息有一些性能上的缺点:

  • 与主体不同,标头不会被压缩。
  • 两个消息之间的标头通常非常相似,但它们仍然在连接中重复传输。
  • 无法多路复用。当在同一个服务器打开几个连接时:TCP 热连接比冷连接更加有效。

HTTP/2 引入了一个额外的步骤:它将 HTTP/1.x 消息分成帧并嵌入到流(stream)中。数据帧和报头帧分离,这将允许报头压缩。将多个流组合,这是一个被称为多路复用(multiplexing)的过程,它允许更有效的底层 TCP 连接。

HTTP 帧现在对 Web 开发人员是透明的。在 HTTP/2 中,这是一个在 HTTP/1.1 和底层传输协议之间附加的步骤。Web 开发人员不需要在其使用的 API 中做任何更改来利用 HTTP 帧;当浏览器和服务器都可用时,HTTP/2 将被打开并使用。

结论

HTTP 消息是使用 HTTP 的关键;它们的结构简单,并且具有高可扩展性。HTTP/2 帧机制是在 HTTP/1.x 语法和底层传输协议之间增加了一个新的中间层,而没有从根本上修改它,即它是建立在经过验证的机制之上。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值