web协议详解与抓包实践

4 ABNF语义定义的HTTP消息格式

这一章主要介绍RFC文档中描述HTTP规则的语法

ABNF核心规则

描述HTTP协议格式

描述HTTP协议格式

5 网络为什么要分层 OSI网络模型与TCP/IP模型

OSI Open System Interconnection Reference Model概念模型

  • 应用层 HTTP/P2P/FTP/telnet
  • 表示层 把网络层的消息转化成应用层能读取的消息 TLS/SSL协议就是工作在表示层
  • 会话层 完全概念化的一层 建立会话 握手 维持连接关闭, 其实这个层有部分工作是表示层和传输层做的, 所以这一层是纯概念化的一层
  • 传输层 TCP协议/UDP协议 解决的是进程与进程之间的通讯, 例如一个网络请求来了 主机应该把这个请求分发给哪个进程, 这一层还做了更多的事情, 例如TCP 保证了请求的可达性, 流量的控制
  • 网络层 IP协议, Inter网 在广域网中, 可以从一个主机上发报文到另一个主机上
  • 数据链路层 在局域网中 我们使用Mac地址连接到相应的交换机/路由器 就可以把报文转到另一个主机上 只工作以太网这样的局域网上
  • 物理层

OSI模型与TCP/IP模型的对照

TCP/IP协议与OSI模型对比

分层的好处是, 每个层做更新 可以不影响到其他层

而坏处就是 每一层的转发其实都是性能的消耗

每一层数据的简称

7 评估Web架构的7大属性

  • 性能
  • 可伸缩性: 支付部署可以互相交互的大量组件
  • 简单性: 易理解 易实现 易验证
  • 可见性: 对于两个组件间的交互进行监视和仲裁的能力
  • 可移植性: 在不同环境下运行的能力
  • 可靠性: 出现部分故障 对整体影响的程度
  • 可修改性: 修改的难易, 由进化性, 可定制性, 可扩展性, 可配置性, 可重用性构成

性能

网络性能

  • 吞吐量: 小于等于带宽
  • 开销: 首次开销 每次开销

用户感知到的性能

  • 延迟: 发起请求到接收到响应的时间
  • 完成时间: 完成一个应用动作所花费的时间

网络效率

  • 重用缓存、减少交互次数、数据传输距离更近、COD(按需代码)

可修改性

  • 可进化性: 一个组件独立升级而不影响其他组件
  • 可拓展性: 向系统添加功能, 而不影响到其他系统的其他部分
  • 可定制性: 临时性、定制性的修改某一要素来提供服务, 而不对常规用户产生影响
  • 可配置性: 应用部署后修改配置提供新的功能
  • 可重用性: 组件不做修改再在其他应用再使用

从5种架构风格推导出HTTP REST

5种架构风格

数据流风格

例如7层网络分层 就是数据流风格

优点: 简单性 可进化性 可拓展性 可配置性 可重用性

管道与过滤器, 每个Filter都有输入端和输出端 只能从输入端读取数据处理完从输出端产生数据

复制风格流

多个进程提供相同的服务, 通过反向代理对外提供集中服务

例如Mysql 冷热备份

还有缓存, 复制请求的结果 为后续的请求复用

分层风格

  • 客户端服务器 Client-Server
  • 分层系统: 每一层为其之上的层服务, 并用在其下层所提供的服务, 例如TCP/IP
  • 分层客户端服务器: 正向代理+反向代理, 从空间上分为外部层和内部层
  • 无状态、客户端服务器: 基于Client-Server, 不允许服务商有session state会话状态, 因为可见性会导致数据重复发送
  • 缓存、无状态、客户端服务器: 用缓存来解决无状态带来的性能消耗
  • 分层、缓存、无状态、客户端服务器

分层风格二

  • 远程会话: CS变体, 服务器保存Apllication state应用状态, 可伸缩性、可见性差
  • 远方数据访问: Application state同时存在于客户端和服务器, 例如mysql命令访问数据库, 几百万数据, 而客户端可以一页页查看 因为游标同时存在于客户端和服务器

移动代码风格

  • 虚拟机: 分离指令和实现
  • 远程求值: 基于CS的VM, 将代码发送至远程服务器执行
  • 按需代码: 服务器在响应中发回处理代码, 在客户端执行
  • 分层、按需代码、缓存、无状态、客户端服务器
  • 移动代理: 相当于远程求值+按需代码的结合

点对点风格

  • Event-based Integration: 基于事件集成系统, 例如kaffa这样的消息系统, 优秀的可重用性,可拓展性, 可进化性, 但缺点是缺乏可理解性, 由于消息广播等因素造成的消息风暴, 可伸缩性差
  • C2: 一带而过
  • DO: 一带而过
  • BDO: 一带而过

    09-如何用Chrome的Network分析网络报文

    过滤器使用技巧

  • 选择过滤多种文件类型: 按ctrl|command 点击则多选

  • domain: 仅显示指定域名 可用*来匹配多个子域名
  • has-reponse-header: 显示指定HTTP响应标头的资源
  • is: is:running表示查找WebSocket资源, is:from-cache表示查找缓存读出的资源
  • lager-than: 显示大于指定大小的资源(单位为字节)
  • method: 显示指定的HTTP请求方法
  • mime-type: 显示指定MIME类型(CONTENT-TYPE)
  • schme: 筛选协议一般写http|https
  • set-cookie-domain: 显示具有Set-Cookie请求头并且domain要匹配, 类似的还有set-cookie-name,set-cookie-value
  • state-code: 显示指定状态码资源

多属性用空格实现AND操作

查看资源是哪个资源引发的

按shift hover到资源名称(A)上

  • 其他资源为红色的表示这些资源由A发起的请求
  • 其他资源为绿色的表示这个资源是发起了A资源请求的

浏览器加载时间

  • 解析HTML结构
  • 加载JS和CSS
  • 解析并执行脚本
  • DOM构建完成
  • 加载图片
  • 页面加载完毕

请求时间详细分部

  • Queueing: 资源正在排队
    • 存在更高优先级的资源
    • 浏览器已打开6个TCP连接, 仅限HTTP1.0/HTTP1.1
    • 浏览器正在分配磁盘空间
  • Stalled: 请求可能会因为Queueing中的原因而停止
  • DNS Loopup: DNS解析时间
  • Proxy Negotiation: 浏览器正在与代理服务器协商请求
  • Request Send: 正在发送请求
  • ServiceWorker Preparation: 浏览器正在启动ServiceWork
  • Request to ServiceWork: 正在请求发送到ServiceWork
  • Wating(TTFB): 浏览器正在等待响应的第一个字节时间(1次往返+服务器响应时间)
  • Content Download: 浏览器正在接受响应
  • Receiving Push: 浏览器通过HTTP2.0服务器推送接受数据
  • Reading Push: 浏览器正在读取之前收到的本地数据

10 URI的基本格式和URI的区别

  • URL: 资源具体的位置
  • URN: 例如magent:?xt=urn:sha1:YNCHXXXXX, 期待为资源提供持久的, 位置无关的标识方式, 并允许将多个命名空间映射到单个URN的命名空格

11 为什么要对URI进行编码

  • 传递数据中, 如果存在分隔符的保留字怎么办
  • 对可能产生歧义性的数据编码
    • 不在ASCII编码的字符
    • URI中规定的保留字
    • 不安全字符 如空格、引号、尖括号等

URI百分号编码

  • 非ASCII编码, 建议先UTF8编码 再US-ASCII编码
  • 对于URI合法字符: 编码与不编码的效果是一致的

不同的语言可能对URI编解码的实现不同

12 详解HTTP请求行

请求方法

  • GET: 主要获取信息的方法 幂等方法
  • HEAD: 类似GET, 但不发送BODY, 用于获取HEAD元数据 幂等方法
  • POST: 常用于新增资源
  • PUT: 更新资源, 带条件时是幂等方法
  • DELETE: 删除资源, 幂等方法
  • CONNECT: 建立tunnel隧道
  • OPTIONS: 显示服务器对访问资源支持的方法

用于文档管理的WEBDAV方法(TFC2518)

  • PROPFIND: 从Web资源从检索以XML格式存储的属性, 可以用来检索远程系统的目录层次结构
  • PROPPATCH: 在单个院子性动作中更改和删除资源的多个属性
  • MKCOL: 创建集合或者目录
  • COPY: 将资源从一个URI复制到另一个URI
  • MOVE: 将资源从一个URI移动到另一个URI
  • LOCK: 锁定一个资源, WEBDAV支持共享锁和互斥锁
  • UNLICK: 解除资源锁定

13 HTTP的正确响应码

响应码分类 1xx

  • 1xx表示请求已收到, 但需要进一步处理才能完成, HTTP1.0不支持
    • 100 Continue: 上传大文件前使用, 由客户端请求中携带Expect: 100-continue头部触发
    • 101 Switch Protocols: 协议升级使用, 由客户端发请请求中携带Upgrade头部触发, 例如升级websocket或者http/2.0
    • 102 Processing: WebDAV请求可能包含很多文件操作, 需要很长时间才完成 该代码表示服务器已接受到请求, 但无响应可用, 这样可以防止客户端超时, 并假设请求丢失

响应码分类 2xx

  • 2xx: 成功处理请求
    • 200 OK: 成功返回响应
    • 201 Created: 有新资源在服务器端被成功创建
    • 202 Accpted: 服务器接收并开始处理请求, 但请求未完成
    • 203 Non-Authoritative Information: 当代理服务器修改了origin server的原始响应宝体时, 代理服务器可以通过此状态码告诉客户端, 203响应可以被缓存
    • 204 No Content: 成功执行了请求且不携带响应包体, 但客户端可以无需更新视图
    • 205 Reset Content: 成功执行了请求且不携带响应包体, 但客户端需要更新视图
    • 206 Partial Content: 使用range协议返回部分响应内容时的响应码
    • 207 Multi-Status: RFC4918, 在WEBDAV协议中以XML返回多个资源的状态
    • 208 Already Reported: RF5842, 在避免相同集合在207响应码下重复上报, 使用208可以使用父集合的响应码

响应码中的 3XX

  • 3xx: 重定向使用Location指向的资源或者缓存中的资源, 在RFC2068中规定客户端重定向次数不应超过5次, 以防止死循环
    • 300 Multiple Choices: 资源有多种表述, 通过300返回给客户端后由其自行选择哪一种表述进行访问
    • 301 Move Permanently: 资源永久重定向到另一个URI中
    • 302 Found: 资源临时的重定向到另一个URI中
    • 303 See other: 重定向到其他资源, 常用于Post/PUT等方法的响应中
    • 304 Not Modified: 当客户端有可能过期的缓存时, 会携带缓存的标识etag, 时间等信息询问服务器缓存是否可复用, 而304是告诉客户端缓存可复用
    • 307 Temporary Redirect: 类似302, 但明确重定向后请求方法必须与原请求方法相同, 不得改变
    • 308 Permanent Redirect: 类似301, 但明确重定向后请求方法必须与原请求方法相同, 不得改变

14 HTTP的错误响应码

  • 400: 客户端出现错误
    • 400 Bad Request: 服务器认为客户端请求错误, 但服务器无法判断是哪种错误 则返回400, 例如HTTP请求格式错误
    • 401 Unauthorized: 用户认证信息缺失或者不正确
    • 407 Proxy Authtication Required: 对需要经由代理的请求, 认证信息未通过代理服务器验证
    • 403 Forbidden: 服务器没有权限执行此请求
    • 404 Not Found: 服务器没找到对应资源
    • 410 Gone: 服务器没找到服务器, 且明确的知道该位置永久性找不到该资源
    • 405 Method Not Allowed: 服务器不支持请求行中的method方法
    • 406 Not Acceptable: 对客户端指定的资源表示不存在的(例如语言|编码有要求), 并把可选择列表返回给客户端
    • 408 Request Timeout: 服务器接受请求超时
    • 409 Conflict: 资源冲突, 例如上传文件时且该位置已存在版本更新的资源
    • 411 Length Required: 如果请求含有包体且未携带 Content-length头部, 且不属于chunks类请求 返回411
    • 412 Precondition Failed: 复用缓存时传递的If-Unmodified-Since或If-None-Match头部不被满足
    • 413 Payload Too Large: 请求包体超出服务器能处理的最大长度
    • 414 URI Too Long:请求URI超过服务器所能接受的长度
    • 415 Unsupported Media Type: 上传的文件类型不被服务器接受
    • 416 Range Not Satisfiable: 无法提供Range请求中指定的那段包体
    • 417 Expectation Failed: 对于Expect请求头部期待的情况无法满足时的响应码
    • 421 Misdirected Request: 服务器认为这个请求不该发给它, 因为它没能力处理
    • 426 Upgrade Required: 服务器拒绝基于当前HTTP协议提供服务, 通过Upgrade头部告诉客户端必须升级才能处理
    • 428 Precondition Required: 用户请求中缺少条件类头部, 例如If-Match-
    • 429 Too Many Request: 客户端发送请求速度过快
    • 431 Request Header Fields Too Large: 请求的HEADER头部大小超过限制
    • 451 Unavailable For Legal Reasons: RFC7725, 由于法律原因不可访问

500 服务器出现错误

错误码 解释
500 Internal Server Error 服务器内部错误, 且不属于以下错误类型
501 Not Implemented  服务器不支持请求所需的功能
502 Bad Geteway 代理服务器无法获取到合法响应
503 Service Unavailable 服务器资源尚未准备好处理当前请求
504 Getway Timeout 服务器无法及时响应
505 Http Version Not Support 请求使用的HTTP协议版本不支持
507 Insufficient Storage 服务器没有足够的空间处理请求
508 Loop Detected 访问资源时检测到循环
511 Network Authentication Required 代理服务器发现客户端需要进行身份验证才能获得网络访问权限

统一规则, 服务器无法判断错误原因, 都返回x00的错误码

15 如何管理跨代理服务器的长短连接

这里跟HTTP权威指南第四章讲得很像 所以也可参考阅读

http://read.404mzk.com/http_power_book.html#4-%E9%93%BE%E6%8E%A5%E7%AE%A1%E7%90%86

长连接和短连接的区别

短连接 在处理请求的时候, 必须每执行完一个请求 都关闭连接 然后再起新的连接 执行新的请求

长连接 在处理请求时 一个TCP连接 可以串行的执行新的请求 但不必关闭请求

客户端与服务器协商使用长连接

客户端在请求头带 Connection: Keep-Alive

服务器响应头也带 Connection: Keep-Alive

HTTP1.1中 默认支持长连接的 所以不带Connection:Keep-Alive

ps: 但是笔者看了chrome 虽然是1.1 但也都是带Connection了 为了统一规范性

客户端/服务器明确不使用长连接 就声明 Connection: Close

其实很少客户端会明确请求头声明Connection: Close

随意笔者测了一下 请求头戴Connection:Close 看服务器是否会返回响应头 Connection: Close

客户端拒绝长连接

果然 服务器返回了Connection: Close

Connection还有一个作用就是

代理服务器不要转发Connection中声明的头部

例如Connection: cookie

假设场景是 客户端A->代理服务器B->代理服务器C

则表示 请求头cookie 只传到代理服务器B, 而代理服务器B 不要把我的cookie传到代理服务器C

Connection 仅对当前连接有效

例如 客户端A->代理服务器B->代理服务器C

这样的话 客户端请求头带 Connection: Keep-Alive的话 只代表客户端A想和代理服务器B做长连接

而客户端A对整条链路后面的代理服务器并没有请求Connection的权利

这里前提是 代理服务器B认识Connection头 不然它只会把Coneection透传下去

Proxy-Connection解决了什么问题

参考书 HTTP权威指南4.5.7 插入Proxy-Connection

16 HTTP消息在服务器端的路由

为了防止陈旧代理服务器

发向正向代理的请求 request-target必须以absolute-from的形式出现

RFC7230规定 必须发送Host|发送多个HOST请求头|HOST格式错误 否则返回400

  • TCP连接
  • 接受请求
  • 根据HOST和端口寻找虚拟主机
  • 寻找URI处理代码
  • 执行处理请求的代码
  • 生成HTTP响应
  • 发送HTTP响应
  • 记录访问日志

17 代理服务器转发消息时相关的头部

多次正向代理反向代理后, 服务器如何拿到用户真正的IP

假设用户经过的代理服务器IP是

115.204.33.1 -> 1.1.1.1 -> 2.2.2.2

那么REF规定的头部是

到达2.2.2.2IP这台机器的时候 其请求头部会有这么一对key-value

X-Forwarded-For: 115.204.33.1, 1.1.1.1

想拿到用户的IP取第一个即可

nginx还实现了非规范的请求头

X-Real-Ip: 115.204.33.1

消息的转发

请求头 说明 例子
Max-forwards 限制Proxy代理服务器的最大转发次数, 仅对TRACE/OPTIONS生效 Max-Forwards = 1, 每层代理服务器都会取值然后减1
Via 表示经过代理服务器的名称和版本 1.0 mzk-nginx, 1.0 mzk-apache
Cache-Control 禁止代理服务器修改响应宝体 Cache-Control: no-transform

18 请求与响应的上下文

请求上下文Referer

一个资源请求的发起, 都会给请求头加上referer, 表示这个请求从哪个请求发起的

浏览器不会放referer的情况

  • data和file协议的资源
  • 当前请求页面采取HTTP, 而发起的请求是HTTPS

作用

  • 统计分析
  • 缓存优化
  • 防盗链

19 内容协商与资源表述

内容协商的两种方式

  • Proactive主动式内容协商: 由客户端请求头描述形式, 服务器根据请求返回对应的内容
  • Reactive 响应式协商: 服务器返回300表示多种选择或者406, 然后再由客户端再次发起请求(支持性差))

场景的协商要素

质量因子: q

Accept: text/html;q=0.9

内容编码: 主要指压缩算法

Accept-Encoding: gzip, deflate, br

表述语言

Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7

资源表述的源文件头部

  • 媒体类型、编码: content-type: text/html; charset=utf-8
  • 内容编码: content-encoding: gzip
  • 语言: Content-Language: de-DE, en-CA

20 HTTP包体的传输方式(1)-定长包体

HTTP-message=start-line *(headed0field CRLF) CRLF [message-body]

以下消息不能有包体

  • HEAD方法请求对应的响应
  • 1xx, 204, 304对应的响应
  • CONNECT方法对应的2XX响应

Content-length方法明确包体总长度(10进制, 包体的字节个数, 且必须与实际传输包体长度一致)

优点: 接收端处理简单

21 HTTP包体的传输方式(2)-不定长宝体

  • 使用Transfer-Encoding头部指明使用chunk传输方式(含Transfer-Encoding头部后Content-Length将会被忽略)

优点

  • 基于长连接持续推送动态内容
  • 压缩体积比较时, 不必完全压缩完(计算头部)再发送, 可以边发送边压缩
  • 传输必须在包体传输完才能计算出Trailer头部

Transfer-conding = chunked | compress | deflate | gzip | transfer-extension

Transfer-Encoding: chunked

chunked-body = * chunk last-chnk trailer-part CRLF

chunk = chunk-size [chunk-ext] CRLF chunk-data CRLF

chunk-size 是16进制

last-chunk = 1*("0") [chunk-ext] CRLF

trailer-part= *(header-field CRLF)

Trailer头部传输

  • 客户端必须表明接受Trailer头部: TE: trailers
  • 服务端必须在刚开始就告诉客户端会在后面携带哪些头部 Trailer: Date
  • 并不是所有trailer-part都允许出现在Trailer头部, 例如Transfer-Encoding和Content-length, Host, Cache-control, Set-Cookie等

Content-Disposition

  • inline: 包体以内联的方式, 作为页面的一部分展示
  • attachment: 指定浏览器将包体以附件的方式下载, Content-Disposition: attachment; name="fileName.jpg";
  • disp-ext-type: 例如在multipart/form-data类型应答中,1 用于子消息体部分 Content-Disposition: form-data; name="fileName.jpg"

22 HTML FROM表单提交时的协议格式

enctype: 在POST方法下 对表单内容在请求包体中的编码格式

- application/x-www-form-urlencoded: 数据编码成以&分隔的键值对, 同时用=分隔key和value, 字符以URL编码方式进行编码

  • multipart/form-data:
    • boundary分隔符
    • 每部分表述皆有HTTP头部描述子包体, 例如content-type
    • last boundary结尾

每部分包体格式 encapsulation = delimiter body-part CRLF

  • delimiter = "--" boundary CRLF
  • body-part = fields (CRLF text)
    • field = field-name ":" [ field-value] CRLF
      • content-disposition: form-data; name="xxxx"
  • close-delimiter = "--" boundary "--" CRLF

23 断点续传与多线程下载是如何做到的

服务器通过Accept-Range头部表示是否支持Range请求

Accept-Ranges: bytes //支持

Accept-Ranges: none //不支持

Range请求范围的单位

基于字节 假设总长为10000

第一个500字节 bytes=0-499

第二个500字节

  • bytes: 500-999
  • bytes: 500-599,600-999

最后一个500字节

  • bytes: -500
  • bytes: 9500-

第一个和最后一个字节

byres=0-0,-1

客户端验证是否过期

服务器响应文件标识头部为 If-Unmodifien-Since或者If-Match

if-range=entity-tag/HTTP-date

  • 使用Etga或者Last modified

服务器响应

格式为 first-byte-pos '-' last-bytes-pos / 完整包体大小

Content-Range: bytes 42-1233/1234 ,

或者

Content-Range: bytes 42-1233/* 未知的文件大小

27 如何合法地跨域请求

跨域请求类型

简单跨域请求

  • GET/HEAD/POST方法之一
  • 仅能使用Cors安全的头部: Accept, Accept-Language, Content-Language, Content-Type
  • Content-Type值只能是: text/plain, multipart/form-data, application/x-www-form-urlencoded其中之一

复杂跨域请求

非简单跨域请求

30 缓存新鲜度的计算

freshness_lifetime 获取的优先级别

s-maxage > max-age > Expries > 预估过期时间

预估过期时间: 浏览器一般根据RFC7234推荐的(DownloadTime - LastMofidied ) * 10%

© 404mzk all right reserved,powered by Gitbookhttp://read.404mzk.com 该文件修订时间: 2020-07-29 12:41:30

results matching ""

    No results matching ""