目录
一. 何为HTTP
1. 简单理解HTTP协议的工作过程
2. Fiddler抓包工具
2.1 抓包工具的原理
二. HTTP 请求解析
1. 首行结构
1.1 认识URL
1.2 HTTP方法
1.3 GET和POST之间的典型区别
2. header 结构
3. 空行
4. body结构
三. HTTP响应解析
1. 常见的状态码
2. 重定向和请求转发
3. 一般自定义的字段
四. 协议格式总结
HTTP,全称为"超文本传输协议",是一种应用非常广泛的传输层协议。日常中浏览器获取到页面,就是基于HTTP的。
所谓 " 超文本 " 的含义 , 就是传输的内容不仅仅是文本 ( 比如 html, css 这个就是文本 ), 还可以是一些其他的资源, 比如图片 , 视频 , 音频等二进制的数据。
我们平时打开一个网站, 就是通过 HTTP 协议来传输数据的,HTTP是浏览器和服务器之间的交互桥梁。例如当我们在浏览器中输入一个 百度 的"网址(URL)"的时候,浏览器会给百度的服务器发送一个http请求,在对方服务器收到这个请求后,经过计算处理,就会返回一个http响应。
而事实上,当我门访问一个网站的时候,可能涉及不止一次http的请求和响应的交互过程。对于这个交互过程,可以借助第三方的工具:Fiddler来进行观察。也就是所谓的抓包工具。fiddler会显示出当前电脑上某个程序使用http和服务器交互的过程。
fiddler本质上是一个代理程序,使用时有两个注意事项:
1. 可能和别的代理程序冲突,因此使用时可能需要关闭其他的代理程序。(一些浏览器插件)
2. 要想正确抓包,需要开启https功能。https是基于http搞出来的进化版协议,当下互联网上绝大部分都是https(https后续会进行讲解),fiddler默认不能抓https的包,此处就需要手动启动https并且安装证书。
代理还分为:正向代理和反向代理,代表着客户端的代理,叫做正向代理;代表着服务器的代理,叫做反向代理。
左侧窗口显示了所有的 HTTP请求/响应, 可以选中某个请求查看详情。
右侧上方显示了 HTTP 请求的报文内容 。( 切换到 Raw 标签页可以看到详细的数据格式 )右侧下方显示了 HTTP 响应的报文内容 。 ( 切换到 Raw 标签页可以看到详细的数据格式 )请求和响应的详细数据 , 可以通过右下角的 View in Notepad 通过记事本打开。
Fiddler相当于是一个代理,当浏览器访问baidu.com的时候,就会把 http请求先发给 fiddler,fiddler再把请求转发给百度的服务器,当百度服务器返回数据的时候,fiddler先拿到返回数据,再把数据交给浏览器。因此 fiddler 对于浏览器和 sogou 服务器之间交互的数据细节, 都是非常清楚的。
一般最关注的是请求搜过的首页页面,因为其他的请求大部分都是基于这个请求产生的。
此处查看上述http请求的数据格式。
一般HTTP请求可以分为四个部分
1.首行
2.请求头:header
3.空行
4.正文:body
首行:一般包含三个部分,之间使用空格来区分。
GET:HTTP的方法;
https://www.baidu.com/:URL,也就是俗称的网址,也称为唯一资源定位符,标识着互联网上的唯一的资源的位置。这里还涉及到另一个概念:URI,表示唯一资源标识符,主要是身份标识,为了和别的资源区分开。而实际上,URL也可以起到身份标识的作效果,所以URL也可以视为一个URI。
HTTP/1.1:版本号;
平时俗称的网址也就是URL。
http : 协议方案名 . 常见的有 http 和 https, 也有其他的类型。 ( 例如访问 mysql 时用的jdbc:mysql )user:pass : 登陆信息, 现在的网站进行身份认证一般不再通过 URL 进行了。 一般都会省略 。www.example.jp : 服务器地址。 此处是一个 " 域名 ", 域名会通过 DNS 系统解析成一个具体的 IP 地址。端口号80: 服务器的端口号。/dir/index.html: 带层次的文件路径。uid=1: 查询字符串(query string)。一般是以?开头,以键值对的方式组织,键值对之间使用&分割,键和值之间使用=进行匹配,此处的键值对的取值和个数,可以是程序员自己约定的,我们可以通过这样的方式来自定制传输我们需要的信息给服务器。片段标识符: 片段标识主要用于页面内跳转,通过不同的片段标识跳转到文档的不同章节,现在一般用不到。
一般而言,URL最关键的四部分:
1.域名/IP;
2. 端口号;
3. 带层次的路径;
4. 查询字符串;
URL中可省略的部分:
协议名 : 可以省略 , 省略后默认为 https://端口号 : 可以省略 . 省略后如果是 http 协议 , 端口号自动设为 80; 如果是 https 协议 , 端口号自动设为 443.带层次的文件路径 : 可以省略 . 省略后相当于 / . 有些服务器会在发现 / 路径的时候自动访问/index.html查询字符串 : 可以省略片段标识 : 可以省略
正如 https://www.baidu.com/ 省略了端口,省略端口的时候,浏览器会提供默认端口号,对于http来说,默认端口是80,对于https来说,默认端口是443,因此输入 https://www.baidu.com:443/也是一个道理。
https://www.baidu.com/ 中文件路径并没有省略,/也表示路径,代表着HTTP服务器的根目录,HTTP服务器是系统上的一个进程,就委托这个服务器管理系统上的一个特定的目录,这个目录里的资源都可以让外面去访问。/管理的根目录,可以是系统上的任意一个目录,这个具体要看http服务器的配置。(一个HTTP服务器提供的资源是很多的,不同的路径,拿到的是不同的资源)一般不同的域名也会对应不同的根目录。
在实际开发中,最常用的HTTP方法就是 GTE 和 POST 。
GET常用于获取服务器上的某个资源,在浏览器中直接输入URL,此时浏览器就会发送出一个GET请求,同时,HTML中的link,img,script等标签,也会触发GET请求,JS中的ajax也能来构造GET请求。但是GET请求是没有正文body部分的。
POST多用于提交用户输入的数据给服务器。POST典型的用于登录,登录跳转就会涉及到POST,上传文件一般也会涉及到POST。POST请求是有正文body部分的。
抓取POST请求的body观察,body 部分一般不为空. body 内的数据格式通过 header 中的 Content-Type 指定. body 的长度由header 中的 Content-Length 指定。一般而言,body部分存放的内容和格式,是由程序员自定义的内容。
header部分:
body部分:
实际上,GET 和 POST 并没有本质区别,在大部分场景下,彼此之间是可以进行相互替代的,但是在使用习惯上,是有一些差别的。
1. GET请求一般是用于从服务器获取数据,POST一般是用于给服务器提交数据;但是采用GET来进行提交,POST来进行获取,也是可以的。
2. GET也可以给服务器传递一些信息,GET传递的信息一般都是放在 query string,POST传递信息则是通过 body。而此处只是一个习惯用法,GET也不是不能有body,POST也不是不能有query string,只不过是少见。
3. GET通常会设计成幂等的,POST不要求幂等。(幂等表示相同的输入,得到的结果也是确定的)
4. GET 可以被缓存的,POST一般不能被缓存。(GET把请求的结果保存下来了,下一次请求的时候就不需要再真请求了,直接读取缓存结果即可。)
从上述抓包结果可以看出,header是以键值对的形式出现的, 每一行是一个键值对,键和值之间使用 : 进行匹配。这些键值对,一般是HTTP事先定义好的,具有特定含义。此处只对一部分稍微重要的键值对进行讲解。
Host:大概描述了服务器主机所在的地址和端口,此处的地址和端口,用来描述最终要访问的目标。此处的内容大概率和URL是一样的,也有一定的概率是不同的,例如,当借助代理服务器来访问某个网站的时候,此时URL描述的是代理服务器的地址,而Host描述的就是另外一个地址。
Content-Length,Content-Type: 分别表示body中的数据长度和数据格式,可想而知,一般情况下,GET不含有body部分,所以GET请求中是没有这两个字段的,POST中有body,则必须有这两个字段。其中Content-Type的格式有很多种:text/html,text/css,image/png,image/jpg,application/javascript,application/json...
User-Agent: 主要描述了浏览器和操作系统的版本,如今User-Agent也多用来区分PC和移动端。
Referer: 当前页面的"来源",表示这个页面是从哪个页面跳转过来的。如果是直接通过地址栏或者直接点击收藏夹,都是没有referer的。
对于这个字段,可以应用于广告收费,例如一条广告,可以发布到不同的平台上去,当用户点击广告,此时就会跳转跳转到广告主对应的网站,同时广告主就要给广告平台发钱。而广告主是会投放广告到不同的平台上的,而对于不同平台的广告点击量肯定是不一样的,此时就需要用referer来进行区分计算了,如果是点击来自于百度平台的广告,此时的referer就是百度,如果是点击来自搜狗平台的广告,此时的referer就是搜狗了,这就通过referer来区分出不同平台上的点击量了。
正因为HTTP是明文传输的,运营商很容易获取并篡改内容,这就涉及到运营商劫持了,也就是来自百度的请求,是有可能被运营线修改为自己的referer,这也才引出了https(后文进行介绍)。
Cookie:这是一个非常重要的header属性。为了保证安全性,网页默认是不能访问计算机的硬盘的。而有时候会需要浏览器能够在本地上存储一些信息,cookie本质上就是浏览器给网页的本地存储数据的机制。
cookie本质上是存在于硬盘上的,cookie就相当于是浏览器对于访问硬盘做出了明确的限制,网页就可以通过操作cookie来存储一些信息。
cookie是通过键值对来组织数据的。而cookie中具体存什么内容,也是由程序员自定义的。
Cookie是从哪来的?
Cookie中的数据是来自于服务器的,服务器会通过HTTP响应的报头部分(Set-Cookie字段)来传输数据。也就是服务器来决定,浏览器的Cookie存什么。
Cookie是在哪里存储的?
Cookie可以认为是存储在浏览器中的,更细分的说,是存储在硬盘上的。Cookie在存储的时候,是根据 浏览器+域名 维度来进行细分的。不同的浏览器,各自存各自的cookie,同一个浏览器的不同域名,也对应这不同的cookie。
cookie中的内容不光有键值对,同时还有过期时间。例如,很多网站登录一次之后,下次登录的时候如果没过过期时间就会进行自动登录。
一般而言,越敏感的信息网站,过期时间就越短。
Cookie要到哪里去?
Cookie一般是要回到服务器中去的。一个服务器通常同一时刻会对应着很多个客户端。客户端这边就会通过cookie来保存当前用户使用的中间状态(此处就类似于上下文),当客户端访问浏览器的时候,就会自动的把cookie的内容带入到请求中去,这样服务器也就可以知道客户端当前的状态了。
cookie就像是服务器在浏览器这边搞了一个寄存器似的。
空行一般就表示header的结束。
因为 HTTP 协议并没有规定报头部分的键值对有多少个, 空行就相当于是 " 报头的结束标记 ", 或者是 " 报头和正文之间的分隔符 "。HTTP 在传输层依赖 TCP 协议, TCP 是面向字节流的 . 如果没有这个空行 , 就会出现 " 粘包问题 "。
正文的具体格式取决于 Content-Type。例如:text/html,text/css,image/png,image/jpg,application/javascript,application/json...此时正文就会以对应的形式出现。
HTTP响应整体上和请求是差不多的,存在一些细节上的差异。
也一般分为四个部分:
1. 首行:版本号 状态码 状态描述符
2. header
3. 空行:表示header的结束
4. body
200 OK:表示成功了;
404 Not Found:访问的资源不存在,也就是在服务器上找不到;
403 Forbidden:访问被拒绝,一般是没有权限访问;
302 Move temporarily:重定向。就是一个老域名是很多人都在用的,但这个时候换新域名了,就可以配置一个重定向,保证老用户在输入老域名的时候,会跳转到新域名上。302这样的响应报文中,会在header里带有个 Location属性,通过这个属性来描述要跳转到哪个新域名上去。而302表示临时重定向,说明只是临时的跳转。
301 Moved Permanently:永久重定向。说明是永久的跳转。504 Gateway Timeout:响应时间过长,浏览器等不及,出现超时情况。500 Internal Server Error:服务器出现内部错误。一般可总结为:2**表示成功;3**表示重定向;4**表示客户端错误;5**表示服务器错误;
重定向是,当前的域名不用了,返回一个新的域名给浏览器,然后浏览器再通过新域名来进行访问。
请求转发是,当前的域名不用了,但是服务器会直接调用新域名的相关代码,返回给浏览器。
由此可见,重定向是可以重定向到外部资源的,也就是可以跳转到别的网站;而请求转发只能在该服务器内部的资源之间进行转发,少了一次交互,但也更高效。各有利弊。
HTTP协议中,还是有不少地方是可以程序员自定义的
1. URL中的路径;
2. URL中的 query string;
3. header中的键值对;
4. header中的cookie键值对;
5. body;