Http Request - HTTP请求那些事情

AI 摘要: HTTP协议主要包括请求和响应两部分,其中请求包括HTTP1.0和HTTP1.1的特征,响应包括HTTP2.0的特征。

1. HTTP 协议概览

1.1. HTTP 不同版本的差异和特征

  • HTTP1.0: 明文、无连接
  • HTTP1.1:
    • 支持持久化(Keep-Alive)操作(发送往 HTTP 协议后,连接不关闭)
    • Pipeline(同时发多个请求,但也存在队头阻塞问题)
    • 支持分块
  • HTTP2.0: 改进性能和效率
    • 二进制 Stream 协议,可以对请求和响应进行优先级排序和流量控制
    • 多路复用(连接复用,复用底层同一个 TCP 连接,避免队头阻塞问题)
    • 头部压缩(降低了传输开销)
    • 支持服务端 Push 推送资源

1.2. HTTP 协议内容

  • 请求:HTTP 请求行、HTTP 请求头、HTTP 请求体
  • 响应:HTTP 响应行、HTTP 响应头、HTTP 响应体
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 请求协议框架
<method> <request-URL> <version>
<headers>

<entity-body>

// 响应协议框架
<version> <status-code> <status-desc>
<headers>

<response-body>

1.3. HTTP 协议请求方式

  • GET、POST、HEAD、OPTIONS、DELETE、PUT、TRACE、CONNECT

1.4. HTTPS 和 TCP 以及 SSL

HTTP 属于应用层协议,依托与底层 TCP/IP 协议栈支持,在发送 HTTP 请求之前,需要先建立连接;考虑到传输安全,引入安全 SSL 来支持(会话层),即 HTTPS 协议

POST 和 GET 请求差异

GET 请求

  • 用于获取资源
  • 参数和值显示在 URL 中
  • 适合非敏感信息
  • 有长度限制
  • 可以被缓存和保存

POST 请求:

  • 用于提交数据
  • POST请求将参数和值包含在请求的正文中,而不是URL中,请求的内容类型(Content-Type)通常设置为application/x-www-form-urlencodedmultipart/form-data,以及application/json
  • 适合敏感信息
  • 没有长度限制
  • 不会被缓存和保存

2. POST 请求

2.1. POST 内容和编码

协议规定POST提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式。实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的HTTP请求满足协议格式就可以。

但是,数据发送出去,还要服务端解析成功才有意义。

一般服务端语言如 php、python 等,以及它们的 framework,都内置了自动解析常见数据格式的功能。

服务端通常是根据请求头(headers)中的Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。所以说到POST提交数据方案,包含了Content-Type消息主体编码方式两部分。

2.2. 表单数据请求

最常见的表单请求,参考:https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4

  1. 确定表单的内容(包含disbaledsubmitcheckboxradioselect
  2. 构建表单数据集
  3. 针对表单数据集,基于content-type指定数据集的编码方式(由 form 表单的enctype属性指定)
    • 内容编码默认采用:application/x-www-form-urlencoded表单 url 编码,相比于块编码,效率更低,适合明文 ASCII 码
    • 内容编按码块编码:multipart/form-data,多用于文件,非 ascii 数据编码,其遵循multipart MIME data streams规则,每个 part 部分包含Content-TypeContent-Disposition,参考后续示例
  4. 最后提交被编码的数据集:通过actionmethod发送给到具体的应用处理代理
    • get 请求:参数通过?追加到action上,然后后续接数据集,编码通过application/x-www-form-urlencoded编码,且仅限制在ASCII码
    • post 请求:参数通过 form 表单的enctype属性指定

3. POST Content-Type 类型

HTTP 协议,在请求过程中,支持不同的Content-Type类型,常见的有text/plain, application/json, application/xml, application/x-www-form-urlencoded, multipart/form-data

3.1. application/x-www-form-urlencoded

最常见的POST提交数据的方式,默认数据基于 urlencode,相比于块编码,效率更低,适合明文 ASCII 码。Ajax 请求,也是用的这种方式,Content-Type默认值都是application/x-www-form-urlencoded;charset=utf-8

1
2
3
4
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

3.2. multipart/form-data

关键点:有边界boundary、适用于大文件传输(大文本、二进制文件)、FORM 表单开启enctype=multipart/form-data选项

通过指定 enctype="multipart/form-data"进行分块传输(在有 files 控件时候一定需要)

1
2
3
4
5
6
7
8
9
<form
  action="http://server.com/cgi/handle"
  enctype="multipart/form-data"
  method="post"
>
  What is your name? <input type="text" name="submit-name" /><br />
  What files are you sending? <input type="file" name="files" /><br />
  <input type="submit" value="Send" /> <input type="reset" />
</form>

户输入 Larry 和上传了一张图片

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Content-Type: multipart/form-data; boundary=AaB03x

--AaB03x
Content-Disposition: form-data; name="submit-name"

Larry
--AaB03x
Content-Disposition: form-data; name="files"
Content-Type: multipart/mixed; boundary=BbC04y

--BbC04y
Content-Disposition: file; filename="file1.txt"
Content-Type: text/plain

... contents of file1.txt ...
--BbC04y
Content-Disposition: file; filename="file2.gif"
Content-Type: image/gif
Content-Transfer-Encoding: binary

...contents of file2.gif...
--BbC04y--
--AaB03x--

3.3. application/json

现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。JSON 格式支持比键值对复杂得多的结构化数据,服务端基本都支持 JSON,适合RESTFUL风格接口。

部分语言如果不支持原生解析,需要一定处理,比如 PHP 在请求头中Content-Typeapplication/json时,从php://input里获得原始输入流,再json_decode成数组对象。

1
2
3
4
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8

{"title":"test","sub":[1,2,3]}