HTTP 全知道:请求与响应的深度剖析
HTTP请求详解
URL
URL(Uniform Resource Locator),统一资源定位符,也是我们常说的 "网址",用于在互联网上标识和定位地址
URL组成
- 协议方案名: 用于访问资源的协议类型,常见的有 HTTP 和 HTTPS
- 例如,在 “https://www.example.com” 中,“https” 就是协议部分。
- 登录信息: (已过时)现在网站一般不会使用URL进行身份认证了
- 服务器地址: 可以是 IP,也可以是 域名(域名会通过DNS解析成IP)
- 服务器端口号: IP确定唯一的主机,端口号确定主机上的程序(端口号省略时,浏览器会通过协议类型自动分配端口号(HTTP协议,浏览器自动加上 80 端口号,HTTPS 协议,浏览器自动加上 443 端口号)
- 例如,“https://www.example.com:8080” 中的 “8080” 就是端口号。
- 带层次的文件路径: 确定服务器上的具体资源(包含很多网页,图片....)
- 例如,在 “https://www.example.com/somepage.html” 中,“/somepage.html” 就是路径部分。
- 查询字符串(Query string): 键值对结构,针对要访问的资源进补充说明
- 键值对之间,使用 "&" 分割
- 键和值之间,使用 "=" 分割
- 例如,“https://www.example.com/search?q=keyword&page=2” 中的 “q=keyword&page=2” 就是查询字符串。( "?" 后面的就是查询字符串)
- query string中的内容是键值对结构, 其中的 key 和 val 的取值和个数,完全都是由程序猿自定义的. 我们可以通过这样的方式自定义信息传输给服务器.
- 片段标识符: 表示一个页面中某个部分的,常见于文档类网站
- 例如,在 “https://www.example.com/page.html#section2” 中,“#section2” 就是片段标识符,它可以用于在页面加载后直接定位到特定的章节或部分。
URL中可以省略的部分
- 协议名:省略后默认为 https://
- IP地址/域名: 在HTML中可以省略, 省略后表示服务器的 ip/域名 与当前 HTML 所属的 ip/域名 一致
- 端口号: 根据协议自动添加端口号. HTTP协议通常为 80 端口号,HTTPS协议通常为 443 端口号
- 带层次的文件路径: 省略后相当于 /. 对于一些网站,当只输入域名而不指定具体路径时,服务器可能会默认返回一个特定的页面,通常是网站的首页
- 查询字符串
- 片段标识符
URL encode
query string 键值对结构值,可以包含各种内容, 万一值里面出现一些特殊的符号,可能是URL解析出现问题(URL中某些符号有特殊含义:例如: ":" "=" "&" "/" "@" "?"......)
URL encode 本质上就是把这些特殊含义的符号经过一些特定的规则给替换掉
转义规则:把要转义的字符/汉字,每个字节用 十六进制 的方式表示出来,给每个字节前面加上 %
例如: 我们在浏览器搜索一下 c++
+ 字符就被转义成了 %2B
方法
方法就是描述了这个 http 请求的"动作"
(图片来自菜鸟教程)
常用的方法有 GET 和 POST
GET
GET 方法是最常用的 HTTP 方法,常用于获取服务器上某个资源.
在浏览器中直接输入某个 URL,此时浏览器就会发出一个 HET 请求
例如: 打开Fiddler进行抓包,打开浏览器 输入 www.baidu.com ,按下回车键
观察FIddler抓包结果
最上面的
是通过浏览器地址栏发送的 GET 请求
HTML页面中很多元素(link,a , img....),能进一步触发 GET 请求(上面图片中带有 baidu(bd) 字样的都是这个页面进一步触发的请求)
还有很多 ajax 产生的
GET 请求的特点
- 首行第一部分为 GET
- query string 可以不为空,也可以为空
- body 为空
- header 部分有若干个键值对结构
POST
POST 方法也是一种常见的方法,通常用于提交用户输入的数据给服务器(例如: 登录/上传文件)
HTTP中的 GET 和 POST 很多时候都是通用的
GET 和 POST 的区别?
首先,先说结论,GET 和 POST其实并没有本质区别(GET 能用的场景,POST 也能用;反之亦然)
但是在使用习惯上还是有区别的:
- 语义不同 : GET 通常用来获取数据, POST 一般用来发送数据
- 传输数据的方式不同:
- GET传输数据,一般是放在 query string中,body 为空
- POST传输数据,一般是放在 body 中,query string 为空
- 是否幂等:
- GET 请求一般是幂等的,POST 请求一般不幂等(如果多次请求得到的结果一样,就视为是幂等的)
- HTTP标准文档建议 GET 为幂等,日常开发中,是否幂等主要看业务需求(比如很多网站都有的 "猜你喜欢" 功能,会根据用户的历史行为进行实时更新)
- GET 可以被缓存(如果被设置成"幂等"),POST 不可以被缓存
补充说明:
- 关于语义:POST 也可以用来获取数据, GET 也可以用来传输数据
- 关于 POST 比 GET 更安全: 是否安全取决于在传输敏感数据(密码/个人信息)时是否进行加密. (POST把数据放在 body 中,浏览器界面上看不见就认为更加安全,有点"掩耳盗铃",密码明文传输,别人只要通过某种方式抓到你传输的数据,密码等敏感信息就泄露了~~)
- 关于数据传输量:有资料说 "GET传输的数据量比POST小",标准文档中没有规定 URL 和 body 的长度. 传输数据量的多少取决于不同浏览器之间的区别
- 关于传输数据类型:"GET 只能传输文本数据,POST 能传输文本数据,也能传输二进制数据",GET 的query string虽然无法直接传输二进制数据,但可以通过 URL encode 将二进制数据进行转换
其他方法
- PUT: 用于更新指定资源的内容
- DELETE: 用于删除指定资源
- PATCH: 用于对资源进行部分更新
- HEAD: 与 GET 类似,只不过只返回响应头,不返回响应体
- TRACE:回显服务器端收到的请求
- OPTIONS:返回服务器所支持的请求方法
请求报头(header)
请求报头是HTTP请求中的重要组成部分,用于向服务器传递关于客户端的附加信息. 请求报头的格式也是 "键值对" 结构
下面介绍几种常见的请求报头.
Host
表示服务器主机的 地址 和 端口
Content-Length
表示 body 中的数据长度. 单位 字节.
Content-Type
告诉服务器发送的 body 的数据格式
请求中的数据格式一般有以下几种:
application/x-www-form-urlencoded
:表单数据,通常用于HTML表单。multipart/form-data
:表单数据,用于文件上传。application/json
:JSON格式的数据。text/xml
或application/xml
:XML格式的数据。text/html
:HTML文档。
例如:
(一个请求/响应当中, 如果没有 body, 也就没有 Content-Length 和 Content-Type)
User-Agent
表示浏览器/操作系统的属性
Cookie
Cookie 是一种小型的数据存储方式,用于在用户的浏览器和服务器之间存储状态信息
-
存储位置:Cookie 存储在用户的本地计算机上,通常保存在浏览器中。
-
创建过程:当用户访问一个网站时,服务器可以发送一个包含 Cookie(Set-Cookie) 的 HTTP 响应。浏览器随后将这些 Cookie 保存在本地,并在后续的请求中自动发送给服务器
以我们熟悉的Gitee为例(已删除Cookie),第一次输入账号密码,发送登录请求,图中的Set-Cookie就相当与设置一个令牌,后续用户继续访问时就会携带这个令牌(相当于我们每个人的身份证,一个独有的身份标识)
后续访问其他页面时
可以看到上图中最后一排的标题是Cookie
画图进一步理解Cookie的设置过程
body
HTTP请求正文(Request Body)是HTTP请求的一部分,它位于请求头(Headers)之后,用于承载客户端向服务器发送的数据。
请求正文可以包含多种类型的数据
例如:
application/x-www-form-urlencoded
multipart/form-data
(用于文件上传)
application/json
text/xml
以上这些类型可以通过抓包查看Content-Type中获得
HTTP响应
状态码
状态表是服务器对客户端请求的响应状态的简短描述,一般分为五种类别
一.1xx(信息状态码)
表示请求已被接收,正在处理
二.2xx(成功状态码)
表示请求正常处理完毕
常见的有: 200 OK 表示请求成功
三.3xx(重定向状态码)
表示为了完成请求,需要进一步操作.
常见的有:
301 Moved Permanently
:请求的资源已被永久移动到新位置。302 Found
:请求的资源临时移动到另一个URI。(在登录页面中经常会见到302,用于实现登录成功后自动跳转界面)304 Not Modified
:自从上次请求后,请求的资源未修改过。
四.4XX(客户端错误状态码)
表示请求有错误,服务器无法处理请求
常见状态码有:
400 Bad Request
:服务器无法理解请求,请求可能不完整。401 Unauthorized
:请求需要用户的身份认证。403 Forbidden
:服务器理解请求但拒绝执行。(有的页面需要登录后有一些权限才能查看)404 Not Found
:服务器找不到请求的资源。408 Request Timeout
:请求超时。
五.5xx(服务器错误状态码)
表示服务器在处理请求的过程中发生了错误
常见状态码:
500 Internal Server Error
:服务器遇到了一个意外情况,无法完成请求。501 Not Implemented
:服务器不支持请求的功能,无法完成请求。503 Service Unavailable
:服务器目前无法处理请求,可能是过载或停机维护。
分享一组梗图:
响应报头"header"
Content-Type
响应中的Content-Type一般有以下几种
响应正文"body"
正文的具体格式取决于Content-Type