文章目录
- HTTP 协议
- HTTP 协议的工作过程
- HTTP 请求 (Request)
- 认识URL
- 关于 URL encode
- 认识 "方法" (method)
- GET 方法
- POST 方法
- 其他方法
- 请求 "报头" (header)
- 请求 "正文" (body)
- HTTP 响应详解
- 状态码
- 响应 "报头" (header)
HTTP 协议
HTTP 协议(超文本传输协议HyperText Transfer Protocol)是属于应用层最广泛使用的协议之一
所谓 “超文本” 的含义, 就是传输的内容不仅仅是文本(比如 html, css 这个就是文本), 还可以是一些其他的资源, 比如图片, 视频, 音频等二进制的数据
浏览器获取到网页, 就是基于 HTTP 协议, HTTP就是浏览器和服务器之间的交互桥梁
HTTP 诞生与1991年. 目前已经发展为最主流使用的一种应用层协议
HTTP 也是基于传输层的 TCP 协议实现的.
所以这个http 格式也是我们需要掌握的内容.
我们平时打开一个网站, 就是通过 HTTP 协议来传输数据的.
当我们在浏览器中输入一个 百度搜索的 “网址” (URL) 时, 浏览器就给百度的服务器发送了一个 HTTP 请求, 百度的服务器返回了一个 HTTP 响应.
这个响应结果被浏览器解析之后, 就展示成我们看到的页面内容. (这个过程中浏览器可能会给服务器发送多个 HTTP 请求, 服务器会对应返回多个响应, 这些响应里就包含了页面 HTML, CSS, JavaScript, 图片, 字体等信息).
HTTP 协议的工作过程
http 协议的交互详细过程, 可以借助第三方工具来看到(抓包工具)
以 Fiddler 为例.(Fiddler下载地址)
注意事项:
fiddle 本质上是一个代理程序, 使用的时候有两个注意事项
- 可能和别的代理程序冲突, 使用的时候要关闭其他的代理程序(包括浏览器的插件)
2.要想正确抓包, 还需要开启 https 功能(https 是基于http的进化版协议, 当下互联网绝大多数服务器都是 https 的, fiddle 默认不能抓 https 的包, 需要我们手动启动一下 https 并且安装证书)
把几个选项勾上即可, 第一次勾选会让你安装证书, 一定要点 “是”
当我们打开百度网站
这些结果就是浏览器在访问百度主页的时候, 产生的 http 请求
浏览器打开一个页面, 对应的 HTTP 请求可能是一个, 也可能是多个.
这个就我们最关注的在请求百度的首页页面, 其他的请求都是基于这个请求产生(百度首页里, 其他代码又产生了别的请求)
我们双击这个请求
就能看到右侧, 上部分是请求的, 下半部分就是响应的
我们点击这个 raw 就能看到这个请求最原始的样子
http 请求, 是具有一定格式的, fiddle 会按照格式解析, 呈现出不同的显示效果, 此处就看最原始的效果
观察抓包结果, 可以看到, 当前的 http 请求, 是个行文本格式的数据
相比于 tcp 这种二进制格式来说, 就更方便用户直接观察
响应数据也是可以点击这个row 来查看响应数据
我们观察这个响应数据, 这个响应数据本来也是文本, 但是有的服务器会对响应进行压缩(就变成二进制了), 压缩是为了节省带宽.
我们也可以对他解压缩, 用记事本查看
这个文本数据就是百度首页. html 里的内容
HTTP 请求 (Request)
我们用记事本打开刚才抓到的请求
这就是请求报文的首行
首行包含三个部分, 之间用空格来区分
GET: 这个是 HTTP 的方法
https://www.baidu.com/ : 这就是 URL (就是我们俗称的网址)
HTTP/1.1 : 版本号
URL 是唯一资源定位符, 用来标识互联网上的唯一的资源的位置(资源在哪, 在哪个服务器的哪个目录的哪个文件…)就是互联网上的具体地址
认识URL
平时我们俗称的 “网址” 其实就是说的 URL (Uniform Resource Locator 统一资源定位符).
互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它.
URL 的详细规则由 因特网标准RFC1738 进行了约定(https://datatracker.ietf.org/doc/html/rfc1738)
https:// : 协议方案名
登录信息(认证) :现在已经不用了.
服务器地址: 域名
服务器端口号: 描述的是哪个程序
带层次的文件路径: 找到程序管辖下的哪个文件
查询字符串: 获取资源的时候带的参数
片段标识符: 现在很少用到
URL 最关键的四个部分:
- 域名
- 端口号
- 带层次路径
- 查询字符串
一个 URL 这里的这几个部分, 有些是可以省略的.
https://www.baidu.com/
这就省略了端口, 省略了端口的时候, 浏览器会提供默认端口
对于http 来说, 默认端口是 80; 对于https 来说, 默认端口是 443
/ 这就是路径, 代表根目录
这是 HTTP 服务器的根目录, HTTP 服务器是系统上的一个进程, 就委托这个服务器管理系统上的一个特定的目录, 这个目录里的资源都可以让外面进行访问.
关于 URL encode
像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现.
比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.
一个中文字符由 UTF-8 或者 GBK 这样的编码方式构成, 虽然在 URL 中没有特殊含义, 但是仍然需
要进行转义. 否则浏览器可能把 UTF-8/GBK 编码中的某个字节当做 URL 中的特殊符号.
转义的规则如下: 将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式
“+” 被转义成了 “%2B”
urldecode就是urlencode的逆过程(解码)
urlincode工具
认识 “方法” (method)
方法描述了这次请求的语义(想干啥)
天下的 HTTP 方法是十斗
GET 独占八斗
POAT 占一斗
剩下的方法分一斗
在实际开发中, 这里的方法大部分都是用不到的, 最常见的就是两个
- GET
- POST
GET 方法
- 在浏览器地址栏里直接输入rul
- html 里的 link, script, img, a …都会触发
POST 方法
典型的就是登录. 登录跳转的时候会涉及 POST
还有就是上传文件
一个 POST 请求可以认为是分成四个部分
- 首行
- 请求头(header)
- 空行
- 正文(body)
如果是 GET 请求, 没有body
如果是 POST 请求一般有 body
在抓包结果中可以看到, post 的 body 是程序员自定义的内容
这里存放的数据的内容和格式, 都是程序员自定义的
GET 和 POST 的典型区别
GET 和 POST 没有本质区别, 在大部分场景下都能相互替代, 只是存在几个习惯上的区别
- GET 也可以给服务器传递一些信息, 一般放在 query string 里
POSR 传递信息则是通过 body
这也只是一个习惯用法, GET 也不是不能有body, POST 也不是不能有 query string 就是非常少见而已
-
GET 请求一般是用于从服务器获取数据
POSR 一般是用于给服务器提交数据 -
GET 通常会被设计成幂等的, POST 不要求幂等
幂等就是:相同的输入, 得到的结果也是确定的
- GET 可以被缓存, POST 则一般不能被缓存
把请求的结果保存下来, 下次请求就不必真请求了, 直接取缓存结果
几个有争议的问题
- GET 请求传输的数据存在上限(1kb 2kb 1024kb…)
实际上 rfc 标准文档中, 对于 HTTP GET 请求的长度上限明确说没有规定,
只是在上古时期的浏览器/服务器, 实现的时候, 搞了个限制, 现在大多都没这种问题了
- POST 比 GET 更加安全
依据就是, 如果是使用 GET 请求进行登录, 此时用户名密码通过 quere string 来传递, 就会出现在浏览器的地址栏中, 一眼就会被别人看到
但是安全指的是, 如果黑客窃取到你的数据上, 你的敏感信息不会泄露, 安全的核心要素是加密呀
其他方法
- PUT 与 POST 相似,只是具有幂等特性,一般用于更新
- DELETE 删除服务器指定资源
- OPTIONS 返回服务器所支持的请求方法
- HEAD 类似于GET,只不过响应体不返回,只返回响应头
- TRACE 回显服务器端收到的请求,测试的时候会用到这个
- CONNECT 预留,暂无使用
请求 “报头” (header)
get 请求报头:
POST 报头:
header 的整体的格式也是 “键值对” 结构
这些键值对都是 HTTP 事先定义好的有特定含义的
Host: 大概描述了服务器所在的 地址 和端口
这里的地址和端口用来描述你最终要访问的目标
这个内容大概率和 URL 中是一样的, 也有一定的情况下是不同的,
Content-Length
表示 body 中的数据长度.
Content-Type
表示请求的 body 中的数据格式.
这里我们要注意的是:
如果是 GET 请求, 没 body, 请求中就没有这两个字段
如果是 POST 请求, 有body 则必须要有这两个字段(习惯上标准, 也不是硬性规定)
User Agent
User Agent 描述了浏览器和操作系统的版本
在早期的浏览器, 只支持文本, 后来浏览器支持图片, 视频, 音频, …
人们用的浏览器版本也参差不齐, 开发者们就想出了, 针对不同的浏览器写多版代码, 通过这个 User Agent 来判断是什么版本的浏览器, 发展到现在, 浏览器也已经很强大了, 这个User Agent 的用武之地也少了很多,
现在主要用来区分是 PC 端还是移动端.
Referer
Referer 描述了当前页面的来源, 如果是直接输入地址, 直接点击收藏夹, 这些是没有 referer
Cookie
Cookie 本质上浏览器给网页提供的本地存储数据的机制(网页默认是不允许访问你计算机的硬盘的, 这也是为了保证安全), 但是网页又有这样的需求, Cookie 就是浏览器对于访问硬盘做出了明确的限制, Cookie 也是在硬盘上放着的, 这样网页就能在Cookie 上存储一些信息.
Cookie 也是通过键值对的方式来组织数据的.
Cookie中具体存在啥内容, 这是程序员自定义的.
这里的数据是啥含义, 那就是开发整个程序的代码的程序员才知道了.
-
那么 Cookie 是从哪里来的呢?
Cookie 中的数据是来自于服务器, 服务器会通过 HTTP 响应的报头部分(Set-Cookie 字段)放到Cookie 里面
服务器来决定, 浏览器的Cookie 里放啥 -
Cookie 是在哪保存的呢?
可以认为是存在于浏览器中, 存在于硬盘的
Cookie 在存的时候, 是按照 浏览器 + 域名 维度来进行细分的.
不同的浏览器, 各自存各自的 Cookie , 同一个浏览器不同的域名, 对应不同的 Cookie
这个Cookie也不是无限期保存的, Cookie 里的内容不光是键值对, 还有过期时间
比如有很多网站, 登录了一次之后, 就会自动记录登录状态, 过了一段时间就需要重新输密码了, 就是这个原因
Cookie 要到哪里去
最终是要回到服务器这里的,
客户端同一时刻是有很多的
客户端这边就会通过 Cookie 来保存当前用户使用的中间状态.
当客户端访问浏览器的时候, 就会自动把 Cookie 的内容带入到请求中, 服务器就能知道现在客户端是啥样子了.
请求 “正文” (body)
-
application/x-www-form-urlencoded
-
multipart/form-data
-
application/json
HTTP 响应详解
这个 HTTP 响应也是分为四个部分
- 首行
HTTP/1.1 200 OK
HTTP/1.1:版本号
200: 状态码
OK: 状态码描述
-
header (响应头)
-
空行
表示 header 的结束标志 -
正文(body)
状态码
HTTP 状态码
描述了这次响应的结果(成功了? 失败了? 原因?)
下面介绍几个常见的
200 OK 这就是成功了
404 Not Found 就是访问的资源不存在, 在服务器上没找到
我们抓包也能看到
403 Forbidden 访问被拒接(没有权限)
302 Move temporarily 重定向(类似于呼叫转移)
302 这样的响应报文中, 会在 header 里带有个 Location 属性, 通过这个属性来描述要跳到哪个新的地址.
500 Internal Server Error 服务器内部错误(服务器代码抛异常了…)
504 Gateway Timeout 相应时间太久, 服务器等不及
这么多的状态码, 可以分成几个大类
响应 “报头” (header)
响应报头的基本格式和请求报头的格式基本一致
小结: