你了解HTTP协议吗?(三)

1.写在前面

前面介绍完了HTTP协议的请求行、响应行,我们继续接下来的内容。

2.如何管理跨代理服务器的长短连接?

HTTP连接的常见的流程

  1. 浏览器解析出主机名
  2. 浏览器查询这个主机名的IP地址(DNS)
  3. 浏览器获得端口号(80)
  4. 浏览器发起到202.43.78.3端口80的连接
  5. 浏览器想服务器发送一条HTTP GET报文
  6. 浏览器从服务器读取HTTP响应报文
  7. 浏览器关闭连接

从TCP编程上看HTTP请求处理

在这里插入图片描述

短连接与长链接

Connection头部

  • Keep-Alive:长连接
    • 客户端请求长连接:Connection:Keep-Alive
    • 服务器表示支持长连接:Connection:Keep-Alive
    • 客户端复用连接
    • HTTP/1.1默认支持长连接 Connection:Keep-Alive无意义
  • Close:短连接
  • 对代理服务器的要求
    • 不转发Connection列出头部,该头部仅与当前连接相关

Connection仅针对当前连接有效

user agent 与 origin server 间有层层proxy代理

在这里插入图片描述

代理服务器对长连接的支持

  • 问题:各方间错误使用了长连接

    • 客户端发起长连接
    • 代理服务器陈旧,不能正确的处理请求的Connection头部,将客户端请求中的Connection:Keep-Alive原样转发给上游服务器
    • 上游服务器正确的处理了Connection头部,在发送响应后没有关闭连接,而试图保持、复用与不认长连接的代理服务器的连接
    • 代理服务器收到响应中Connection:Keep-Alive后不认,转发给客户端,同时等待服务器关闭短连接
    • 客户端收到了Connection:Keep-Alive,认为可以复用长连接,继续在该连接上发起请求
    • 代理服务器出错,因为短连接上不能发起两次请求
  • Proxy-Connection

    • 陈旧的代理服务器不识别该头部:退化为短连接

    • 新版本的代理服务器理解该头部 与客户端建立长连接 与服务器使用Connection替代Proxy-Connect头部

      在这里插入图片描述

3.HTTP消息在服务器端的路由

Host头部

Host = uri-host[“:” port]

  • HTTP/1.1规范要求,不传递Host头部则返回400错误响应码
  • 为防止陈旧的代理服务器,发向正向代理的请求request-target必须以absolute-form形式出现
    • request-line = method SP request-target SP HTTP-version CRLF
    • Absolute-form = absolute-URI = scheme “:” hier-part[“?” query]

Host头部与消息的路由

  1. 建立TCP连接 确定服务器的IP地址
  2. 接收请求
  3. 寻找虚拟主机 匹配Host头部和域名
  4. 寻找URI的处理代码 匹配URI
  5. 执行处理请求的代码 访问资源
  6. 生成HTTP响应 各中间件基于PF架构串行修改响应
  7. 发送HTTP响应
  8. 记录访问日志

在这里插入图片描述

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

客户端与源服务器间存在多个代理

在这里插入图片描述

问题:如何传递IP地址?

  1. TCP连接四元组(src ip, src port, dst ip, dst port)
  2. HTTP 头部X-Forwarded-For用于传递IP
  3. HTTP 头部X-Real-IP用于传递用户IP
  4. 网络中存在许多反向代理**(前提)**

在这里插入图片描述

在这里插入图片描述

消息的转发

  • Max-Forwards头部 限制Proxy代理服务器的最大转发次数,仅对TRACE/OPTIONS方法有效 Max-Forwards = 1*DIGIT
  • Via头部 指明经过的代理服务器名称及版本
  • Cache-Control:no-transform 禁止代理服务器修改响应包体。

5.请求与响应的上下文

请求的上下文:User-Agent

指明客户端的类型信息,服务器可以据此对资源的表述做抉择

  • User-Agent = product * (RWS (product / comment))
  • product = token [“/” product-version]
  • RWS = 1 *(SP / HTAB)

请求的上下文:Referer

浏览器对来自某一页面的请求自动添加的头部

  • Referer = absolute-URI / partial-URI
  • Referer 不会被添加的场景
    • 来源页面采用的协议为表示本地文件的"file"或者"data" URI
    • 当前请求页面采用的是http协议,而来源页面采用的是https协议
  • 服务器端常用于统计分析、缓存优化、防盗链等功能

请求的上下文:From

主要用于网络爬虫,告诉服务器如何通过邮件联系到爬虫的负责人

响应的上下文:Server

指明服务器上所用软件的信息,用于帮助客户端定位问题或者统计数据

  • Server = product *(RWS (product / comment))
  • product = token [“/” product-version]

响应的上下文:Allow与Accept-Ranges

Allow:告诉客户端,服务器上该URI对应的资源允许哪些方法的执行

  • Allow = #method

Accept-Ranges:告诉客户端服务器上该资源是否允许range请求

  • Accept-Ranges = acceptable-ranges

6.内容协商和资源表述

内容协商

每个URI指向的资源可以是任何事物,可以有多种不同的表述,例如一份文档可以有不同语言的翻译、不同的媒体格式、可以针对不同的浏览器提供不同的压缩编码等。

在这里插入图片描述

内容协商的两种方式

  • Proactive 主动式内容协商:指由客户端在请求头部中提出需要的表述形式,而服务器根据这些请求头部提供特定的representation表述

在这里插入图片描述

  • Reactive 响应式内容协商:指服务器返回300 Multiple Choices 或者 406 Not Acceptable,由客户端选择一种表述URI使用

    在这里插入图片描述

常见的协商要素

  • 质量因子q:内容的质量、可接受类型的优先级
  • 媒体资源的MIME类型及质量因子。
  • 字符编码:由于UTF-8格式广为使用,Accept-Charset已被废弃
  • 内容编码:主要指压缩算法 Accept-Encoding:gizp, deflate,br
  • 表述语言:Accept-Language

国际化与本地化

  • Internationalization (i18n,i和n间有18个字符)
    • 指设计软件时,在不同的国家、地区可以不做逻辑实现页面的修改便能够以不同的语言显示
  • localization (l10n,l和n间有10个字符)
    • 指内容协商时,根据请求中的语言及区域信息,选择特定的语言作为资源表述

资源表述的元数据头部

  • 媒体类型、编码 content-type
  • 内容编码 content-encoding
  • 语言 content-language

7.HTTP包体的传输方式

HTTP包体:承载的消息内容

  • 请求或响应都可以携带包体

    • HTTP-message = start-line * (header-field CRLF) CRLF [message-body]
    • message-body = *OCTET:二进制字节流
  • 以下消息不能含有包体

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

两种传输HTTP包体的方式

  • 发送HTTP消息时已能够确定包体的全部长度

    • 使用Content-Length头部明确指明包体长度 Content-Length = 1*DIGIT 用10进制表示包体中的字节个数,且必须与实际传输的包体长度一致。
    • 如果包体的长度小于实际的长度,这个时候再TCP协议的层面是发送实际的长度,但是在HTTP协议层实际上只发送了包体的长度。
    • 如果包体的长度大于实际的长度,这个时候浏览器会直接无法解析
  • 优点:接收端处理更简单

  • 发送HTTP消息时不能确定包体的全部长度

    • 使用Transfer-Encoding头部指明使用Chunk传输方式
    • 含Transfer-Encoding头部后Content-Length头部应被忽略
  • 优点

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

不定长包体的chunk传输方式

  • Transfer-Encoding头部
    • transfer-coding = “chunked” / “compress” / “deflate” / “gzip” / transfer-extension
    • chunked transfer encoding 分块传输编码:Transfer-Encoding:chunked
    • chunked-body = *chunk last-chunk trailer-part CRLF
    • chunk = chunk-size [chunk-ext] CRLF chunk-data CRLF chunk-size = 1*HEXDIG chunk-data = 1*OCTET
    • last-chunk = 1*(“0”)[chunk-ext] CRLF
    • trailer-part = *(header-field CRLF)

Trailer头部的传输

  • TE头部:客户端在请求在声明是否接受Trailer头部
    • TE:trailers
  • Trailer头部:服务器告知接下来chunk包体后传输哪些Trailer头部
    • Trailer:Date
  • 以下头部不允许出现在Trailer值中:
    • 用于信息分帧的首部(例如 Transfer-Encoding 和 Content-Length)
    • 用于路由用途的首部 (例如Host)
    • 请求修饰首部(例如控制类和条件类的,如Cache-Control Max-Forwards 或者TE)
    • 身份验证首部(例如Authorization 或者 Set-Cookie)
    • Content-Encoding Content-Type Content-Range,以及Trailer自身

MIME

MIME(Multipurpose Internet Mail Extensions)

content:=“Content-Type”“:”“type”/“subtype*(”;"parameter)

  • type := discrete-type / composite-type

  • discrete-type := “text”/“image”/“audio”/“video”/“application”/extension-token

  • composite-type := “message” / “multipart” /extension-token

  • subtype := extension-token / iana-token

  • parameter := attribute “=” value

大小写不敏感,但通常是小写

Content-Disposition头部

  • disposition-type = “inline” | “attachment” | disp-ext-type
    • inline:指定包体是以inline内联的方式,作为页面的一部分展示
    • attachment:指定浏览器将包体以附件的方式下载
    • 在multipart/form-data类型应答中,可以用于子消息体部分

8.HTML form 表单提交时的协议格式

HTML FORM表单

HTML:HyperText Markup Language,结构化的标记语言 浏览器可以将HTML文件渲染为可视化网页

FORM表单:HTML中的元素,提供了交互控制元件用来向服务器通过HTTP协议提交信息,常见控件有:

  • Text Input Controls:文本输入控件
  • Checkboxes Controls:复选框控件
  • Radio Box Controls:单选框按钮控件
  • Select Box Controls:下拉列表控件
  • File Select boxes:选取文件控件
  • Clickable Buttons:可点击的按钮控件
  • Submit and Reset Button:提交或者重置按钮控件

HTML FORM 表单提交请求时的关键属性

action:提交时发起HTTP请求的URI

method:提交时发起HTTP请求的http方法

  • GET:通过URI,将表单数据以URI参数的方式提交
  • POST:将表单数据放在请求包体中提交

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

  • application/x-www-form-urlencoded 数据被编码成以’&'分隔的键-值对,字符以URL编码方式编码
  • multipart/form-data
    • boundary 分隔符
    • 每部分表述皆有HTTP头部描述子包体,例如Content-Type
    • last boundary 结尾

multipart: 一个包体中多个资源表述

  • Content-type 头部指明这是一个多表述包体
    • Content-type: multipart/form-data
  • Boundary 分隔符的格式
    • boundary := 0*69 bcharsnospace
      • bchars := bcharsnospce /“”
      • bcharsnospace := DIGIT / ALPHA / “'” / “(” /“)” / “+” /“_” /“,” / “-” /“.” /“/” /“:” / “=” /“?”

Multipart包体格式

multipart-body = preamble 1*encapsulation close-delimiter epilogue

  • premble := discard-text
  • epilogue := discard-text
    • discard-text := *(*text CRLF)
  • 每部分包体格式:encapsulation = delimiter body-part CRLF
    • delimiter = “–” boundary CRLF
    • body-part = fields *(CRLF * text)
      • field = field-name “:” [field-value] CRLF
  • close-delimiter = “–” boundary “–” CRLF

9.断点续传与多线程下载如何做到?

多线程、断点续传、随机点播等场景的步骤

  1. 客户端明确任务:从哪开始下载
    • 本地是否已有部分文件
      • 文件已下载部分在服务端发生改变?
    • 使用多个线程并发下载
  2. 下载文件的指定部分内容
  3. 下载完毕后拼装成统一的文件

HTTP Range规范

  • 允许服务器基于客户端的请求只发送响应包体的一部分给到客户端,而客户端自动将多个片断的包体组合成完整的体积更大的包体
    • 支持断点续传
    • 支持多线程下载
    • 支持视频播放器实时拖动
  • 服务器通过Accept-Range头部表示是否支持Range请求
    • Accept-Ranges:bytes 支持
    • Accept-Ranges:none 不支持

Range请求范围的单位

基于字节,设包体总长度为10000

  • 第1个500字节:bytes=0~499
  • 第2个500字节:bytes = 500~999 bytes = 500600,601999 bytes = 500700,601999
  • 最后一个500字节:bytes = -500 bytes = 9500-
  • 仅要第1个和最后1个字节:bytes = 0-0,-1

通过Range头部传递请求范围。

Range条件请求

  • 如果客户端已经得到了Range响应的一部分,并想在这部分响应为过期的情况下,获取其他部分的响应
    • 常与If-Unmodified-Since或者If-Match头部共同使用
  • If-Range = entity- tag / HTTP-date
    • 可以使用Etag或者Last-Modified

服务器响应

206Partial Content

  • Content-Range头部:显示当前片断在完整包体中的位置
  • Content-Range = byte-conent-range /other-content-range
    • Byte-content-range = bytes-unit SP (byte-range-resp / unsatisfied-range)
      • Byte-range-resp = byte-range “/” (complete-length / “*”)
      • Complete-length = 1*DIGIT 完整资源的大小,如果未知则用*号替代
      • Byte-range = first-byte-pos “-” last-byte-pos

416Range Not Satisfiable

  • 请求范围不满足实际资源的大小,其中Content-Range中的complete-length 显示完整响应的长度。

200 OK

  • 服务器不支持Range请求时,则以200返回完整的响应包体

多重范围与multipart

  • 请求
    • Range:bytes = 050,100150
  • 响应
    • Content-Type: multipart/byteranges;boundary=…

10.Cookie的格式与约束

Cookie是什么?

保存在客户端、由浏览器维护、表示应用状态的HTTP头部

  • 存在在内存或者磁盘中

  • 服务端生成Cookie在想用中通过Set-Cookie头部告知客户端(允许多个Set-Cookie头部传递多个值)

  • 客户端得到Cookie后,后续请求都会自动将Cookie头部携带至请求中

    在这里插入图片描述

Cookie与Set-Cookie头部的定义

  • Cookie头部中可以存放多个name/value名值对
    • Cookie-header = "Cookie: " OWS cookie-string OWS
    • Cookie-string = cookie-pair * (“;” SP cookie-pair)
    • Cookie-pair = cookie-name “=” cookie-value
  • Set-Cookie 头部一次只能传递1个name/value名值对,响应中可以含多个头部
    • Set-cookie-header = “Set-Cookie:” SP set-cookie-string
    • Set-cookie-string = cookie-pair * (“;” SP cookie-av)
    • Cookie-pair = cookie-name “=” cookie-value
    • Cookie-av: 描述Cookie-pair的可选属性

Set-Cookie中描述cookie-pair的属性

Cookie-av = expires-av /max-age-av / domain-av / path-av / secure-av / httponly-av / extension-av

  • expies-av = “Expires=” sane-cookie-date cookie到日期sane-cookie-date后失效
  • max-age-av = “Max-Age=” non-zero-digit *DIGIT cookie经过*秒后失效。max-age优先级高于expires
  • domain-av = “Domain” = domain-value 指定cookie可用于哪些域名,默认可以访问当前域名
  • path-av = “Path=” path-value 指定Path路径下才能使用cookie
  • secure-av = “Secure” 只有使用TLS/SSL协议(https)时才能使用cookie
  • Httponly-av = “HttpOnly” 不能使用JavaScript(Document.cookie 、XMLHttpRequest、Request APIs)访问到cookie

Cookie使用的限制

RFC规范对浏览器使用Cookie的要求

  • 每条Cookie的长度至少要支持达到4KB
  • 每个域名下至少支持50Cookie
  • 至少要支持3000个Cookie

代理服务器传递Cookie时会有限制

Cookie在协议设计上的问题

Cookie会被附加在每个HTTP请求中,所以无形中增加了流量

由于在HTTP请求中的Cookie是明文传递的,所以安全性成问题(除非用HTTPS)

Cookie的大小不应超过4KB,故对于复杂的存储需求来说是不够用的

11.Session的工作的原理

常见的登录的场景下的Cookie与Session的常见用法

在这里插入图片描述

无状态的REST架构VS状态管理

应用状态与资源状态

  • 应用状态:应由客户端管理,不应由服务器管理

    • 如浏览器目前在哪一页
    • REST架构要求服务器不应保存应用的状态
  • 资源状态:应有服务器管理,不应由客户端管理

    • 如数据库中存放的数据状态,例如用户的登录信息。
  • HTTP请求的状态

    • 有状态的请求:服务端保存请求的相关的信息,每个请求可以使用一起保留的请求相关信息
      • 服务器session机制使服务器保存请求的相关信息
      • cookie使请求可以携带查询信息,与session配合完成有状态的请求
    • 无状态的请求:服务器能够处理的所有信息都来自当前请求所携带的信息
      • 服务器不会保存session信息
      • 请求可以通过cookie携带

第三方Cookie

浏览器允许对于不安全域下的资源(如广告图片)响应中的set-Cookie保存,并在后续访问该域时自动使用Cookie

  • 用户踪迹信息的搜索

12.写在最后

本节博客主要介绍了代理服务器的长短连接,HTTP消息在服务器端的路由,代理服务器转发消息时的相关头部,请求与响应的上下文,内容协商和资源表述,HTTP包体的传输方式,HTML form 表单提交时的协议格式,断点续传与多线程下载如何做到,Cookie的格式与约束,Session的工作的原理。

猜你喜欢

转载自blog.csdn.net/qq_36434742/article/details/125066152