03-HTTP

nobility 发布于 2020-03-24 880 次阅读


HTTP

特点

  • 客户端/服务端模式,只能由客户端发送请求之后才能得到服务端响应
  • 请求时只需传送请求方法和资源路径
  • 可以传输任意类型的数据,类型由Content-Type字段标记
  • 默认情况下一个请求由一个连接处理,请求结束后就断开连接
  • 无记忆之前的数据,需要依赖CookiesSession等数据存储才能实现记忆之前的数据

URI

URI(统一资源标识符),主要包括两类:

  • URL(统一资源定位符):protocol://[username:password@]host:port/path[?query#hash]
    • protocol:使用的协议,若没有此字段顶多称为URI而不能称为URL
    • username:password:登入的用户名和密码,一般也没有人会这样用,因为太不安全了
    • host:port:主机和端口,主机可以是IP也可以是域名,域名会通过DNS解析成相应的IP
    • path:服务器软件资源目录中的路径
    • query:查询字符串,使用key=value的形式,多个键值对使用&分隔
    • hash:页面片段哈希值,前端通常当作锚点定位使用
  • URN(统一资源命名符):urn:hierarchical
    • urn:表明是一个URN,若没有此字段顶多称为URN而不能称为URL
    • hierarchical:该资源的层级关系,多个层级使用:分隔,比如人:男人:张三

乱码的原因

  1. 编码和解码使用的方式不一致
  2. 使用的编码方式中没有对应的字符集,即时解码方式一致也不会出现正确的结果

URL中的百分号编码,会对不属于ASCII码的字符和属于ASCII码但是又属于保留字的字符进行百分号编码,百分号编码就是对非ASCII码取Unicode内码再加%前缀

HTTP报文

HTTP报文格式

常用请求方法

  • GET:作为URL的一部分向服务器端发送,是浏览器默认请求方式
    • 由于是URL的一部分,所以很容易从浏览历史记录中查到表单提交内容,不太安全
    • 由于是URL的一部分,所以请求体就是URL中的query部分,没有显示的请求体
    • URL长度有限制
  • POST:用于提交表单数据或大批量的数据
    • 有自己的请求体,相对比较安全
    • 没有长度限制,所以可以提交大批量数据
  • PUT:用于更新数据资源
    • HTTP1.1版本不带有PUT方法的验证机制,所以存在一定的安全隐患,一般不使用
  • DELEAT:用于删除数据资源
    • HTTP1.1版本不带有DELEAT方法的验证机制,所以存在一定的安全隐患,一般不使用
  • HEAD:与GET请求相同,不同的是只获取响应头,而没有响应体,所以多作用与超链接弹探测
  • OPTIONS:用于查询接口支持的请求什么方法
  • TRACE:回显服务器收到的请求,主要用于测试和诊断,容易引起一种XST(跨站追踪)的攻击方式,所以一般不使用
  • CONNECT:开启客户端与请求资源之间的双向沟通通道,通常用于访问代理服务器

常用响应状态码

  • 1XX:临时响应,已经接受需要继续处理,没有响应体
  • 2XX:成功
    • 200 OK:请求已成功
    • 202 Accepted:已接受,但未处理完成
    • 206 Partial Content:服务器成功处理了部分内容,多用于请求部分内容,即断点续传完成
  • 3XX:重定向
    • 301 Moved Permanently:永久移动,URI会变,浏览器会有缓存
    • 302 Found:临时移动,URI不会变,浏览器不会有缓存
    • 304 Not Modified:文件未修改,使用本地缓存文件
  • 4XX:客户端请求错误
    • 400 Bad Request:客户端语法错误
    • 401 Unauthorized:未授权的,请求要求客户身份认证
    • 403 Forbidden:拒绝访问,没有权限
    • 404 Not Found:资源未找到
    • 406 Non Acceptable:无可接收的媒体类型
    • 416 Range Not Satisfiable:请求部分资源内容范围错误
  • 5XX:服务器错误
    • 500 Internal Server Error:服务器内部错误,无法完成请求
    • 502 Bad Gateway:网关或代理服务器错误,无效的请求

报文头

通用报文头

可以通用于请求报文头和响应报文头

字段名 描述
Cache-Control 缓存控制
Connection 逐跳首部,连接管理
Date 创建报文的日期时间
Pragma 报文指令
Trailer 报文末端的首部
Transfer-Encoding 指定报文主体的传输编码
Upgrade 升级为其他协议
Via 代理服务器的相关信息
Warning 错误通知
  • Connection:连接管理
    • keep-alive:网页打开请求结束后不会断开TCP连接,若再次发送请求还会使用该连接,HTTP1.1默认采用长连接
    • close:请求结束后就会断开TCP连接,若再次发送请求会重新建立连接,HTTP1.0默认采用短连接
请求报文头

只在请求头中出现

字段名 描述
Accept 优先媒体类型
Accept-Charset 优先字符集编码
Accept-Encoding 优先内容编码
Accept-Language 优先自然语言
Authorization Web认证信息
Expect 期待服务器的特定行为
From 用户电子邮箱地址
Host 请求资源服务器地址和端口号
If-Match 比较实体标记(ETag)
If-None-Match 比较实体标记
If-Modified-Since 比较资源更新时间
If-Unmodified-Since 比较资源的更新时间
If-Range 资源未更新时发送实体Byte的范围请求
Max-Forwards 最大传输逐跳数
Proxy-Authorization 代理服务器要求客户端的认证信息
Range 实体的字节范围请求
Referer 对请求中URI的原始获取放
TE 传输编码优先级
User-Agent HTTP客户端程序信息
  • Host:请求资源服务器地址和端口号,是直接从URL中截取出来的,可能是IP也可能是域名
  • Referer:告知服务器是从那个连接中跳过来的
  • User-Agent:客户端使用的操作系统、浏览器名称和版本信息
响应报文头

只在响应头中出现

字段名 描述
Accept-Ranges 是否接受字节范围请求
Age 推算资源创建经过时间
ETag 资源的匹配信息
Location 令客户端重定向到指定的URI
Proxy-Authenticate 代理服务器对客户端的认证信息
Retry-After 对再次发起请求的时机要求
Server HTTP服务器的安装信息
Vary 代理服务器缓存的管理信息
WWW-Authenticate 服务器对客户端的认证信息
实体报文头

用来描述实体

字段名 描述
Allow 资源可支持的HTTP方法
Content-Encoding 实体主体使用的编码方式
Content-Language 实体主体的自然语言
Content-Length 实体主体的大小,以字节为单位
Content-Location 其实是代替对应资源的URI
Content-MD5 实体主体的报文摘要
Content-Range 实体主体的位置访问
Content-Type 实体主体的媒体类型
Expires 实体主体的过期的日期时间
Last-Modified 资源的最后修改日期时间

CORS跨域请求

需要浏览器和服务器都支持,目前所有浏览器都支持,整个CORS通信过程,浏览器都是自动完成的,浏览器一旦发现AJAX请求跨域,就会自动附加一些头部信息,所以实现CORS通信的关机是服务器

简单请求

简单的说简单请求就是简单的请求方法和简单的请求头的结合,表单请求也是简单请求,表单请求在历史上是一直可以跨域请求的

  • 请求方法是:HEADGETPOST

  • 请求头只有:

    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:仅限三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

简单请求流程

浏览器直接发出CORS请求,在请求头中添加一个Origin字段来标明本次请求来自哪个域(协议+域名+端口)

  • 若该域不在许可范围内,服务器会返回一个正常的HTTP响应,这个正常的响应中没有包含Access-Control-Allow-Origin字段,所以浏览器就会忽略掉接收请求,就会抛出一个错误被XMLHttpRequestonerror回调函数捕获,这种错误是无法使用状态码来判断的,因为是一个正常的HTTP响应
  • 若该域在许可范围内,服务器就会在响应头中添加以下三个字段
    • Access-Control-Allow-Origin:该字段是必须的,要么是*表示可接受任意域请求,要么与请求时的Origin的值相同(要注意域名和IP的映射关系浏览器是不知道的,所以也属于不同域,而且只能设置一个值,若想设置多个就需要在程序中实现)
    • Access-Control-Allow-Credentials:该字段可选,它的值是一个布尔值,表示是否允许浏览器发送Cookie,默认不发送(不设置就相当于false),只能设置为true;若只是将XMLHttpRequestwithCredentials设置为true,但是服务器不允许发送Cookie,则浏览器不会将响应内容返回给请求者,只有两者同时为true才行;设置上传Cookie后Access-Control-Allow-Origin字段就不能使用*,必须与请求网页同域,Cookie依然遵循同源政策,也就是上传是AJAX请求域的Cookie而不是当前页面的Cookie,当前页面也无法拿到AJAX请求域的Cookie
    • Access-Control-Expose-Headers:该字段可选,在CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个服务器返回的基本字段,若想使用该方法拿到其他的字段(包括自定义字段)就需要在该字段指定;6个基本字段包括:``Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma`
非简单请求

非简单请求的CORS请求,会在正式通信前增加一次HTTP查询请求,询问服务器当前页面域名是否在服务器允许跨域白名单中,以及可以使用哪些HTTP方法和请求头字段,只有得到肯定的答复,浏览器才会发出正式的AJAX请求,否则就会报错

比如:请求方法是PUTDELETEContent-Type字段的类型是application/json

1. 预检请求

  • 预检请求使用的是OPTIONS方法
  • 主要有这几个字段来进行询问
    • Origin:标明请求来自哪个域
    • Access-Control-Request-Method:要使用的请求方法
    • Access-Control-Request-Headers:要使用哪些自定义请求头字段,多个可使用逗号分隔

2. 预检请求响应

  • 主要有对应的字段来进行响应
    • Access-Control-Allow-Origin:允许跨域的域
    • Access-Control-Allow-Methods:允许使用的请求方法,多个用逗号分隔
    • Access-Control-Allow-Headers:允许使用的自定义请求头字段,多个用逗号分隔
    • Access-Control-Allow-Credentials:是否需要发送Cookie,与简单请求中的一致
    • Access-Control-Max-Age:指定多久之内不需要在发送预检请求,以秒为单位
  • 允许:上述的字段的值都应该大于等于(预检请求的值都包含在预检响应中)请求允许
  • 不允许:返回一个正常的HTTP响应,但是没有任何CORS相关字段或者明确表示请求不符合条件,这时,浏览器就会认定,服务器不同意预检请求,因此触发一个错误,被XMLHttpRequest对象的onerror回调函数捕获

3. 浏览器的正常请求和响应

一旦预检请求通过后,就都跟简单请求一样,请求头会增加一个Origin头信息字段,响应体会增加一个Access-Control-Allow-Origin字段

HTTP缓存

  • Cache-Control:缓存控制
    • no-store:所有内容都不缓存
    • no-cache:缓存,但是缓存前会判断缓存资源是否是最新
    • no-transform:代理服务器无法修改缓存内容,只是声明性的
    • max-age=x:请求缓存缓存后x秒内不再发起请求,与Expires类似,是HTTP1.1的属性,与Expires共存的情况下优先级高于Expires
    • s-maxage=x:代理服务器请求源站点缓存后x秒内不再发起请求
    • max-stale=x:即使缓存已经过期了,但是在x秒内可以使用过期缓存
    • public:客户端和代理服务器都可以缓存
    • private:只能客户端可以缓存,只是声明性的

原理

使用Cache-Control字段即可启动缓存机制,详细的缓存控制在上面通用报文头中

  • max-age=x:请求缓存缓存后x秒内不再发起请求,与Expires类似,是HTTP1.1的属性,与Expires共存的情况下优先级高于Expires
  • Expires:实体主体的过期的日期时间,与缓存控制中的max-age=x类似,是HTTP1.0的字段,与max-age=x共存的情况下,优先级低于max-age=x
  • If-Modified-Since:比较资源更新时间,最短时间是以秒为单位的,由于在请求头中出现,所以是客户端告诉服务器,与响应头中的Last-Modified是一对
  • Last-Modified:资源的最后修改日期时间,最短时间是以秒为单位的,由于在响应头中出现,所以是服务器告诉客户端,与If-Modified-Since是一对
  • ETag 资源的匹配信息,由文件内容生成,解决了以秒为单位的长时间限制,与If-None-Match是一对
  • If-None-Match 比较实体标记,由文件内容生成,解决了以秒为单位的长时间限制,与ETag是一对

使用缓存的流程

  1. 开启缓存,先由过期时间起到作用,在一定时间内使用本地缓存,要注意Expires的优先级低于max-age=x,也就是说共存情况下Expires将无效
  2. 再由资源文件的标记信息起作用,也就是说同时设置了Last-ModifiedETagLast-Modified将无效
  3. 若未设置ETag文件标记,则才会使用Last-Modified对比文件是否修改

由步骤可知道,缓存的问题就是服务器更新,这些更新条件都是在文件过期的情况下对比文件是否跟新,为了解决这个问题,需要采用md5/hash值对静态资源文件进行唯一标识名,当服务器更新时,文件的名字就会更改,名字更改了就不会在使用缓存

浏览器操作对缓存的影响

用户操作 过期时间 文件对比
地址栏回车 有效 有效
页面连接跳转 有效 有效
新打开窗口 有效 有效
前进后退 有效 有效
F5刷新 无效 有效
Ctrl+F5强制刷新 无效 无效

内容协商

原理

请求头 描述 响应头
Accept 媒体类型 Content-Type
Accept-Charset 字符集 Content-Type
Accept-Encoding 编码 Content-Encoding
Accept-Language 自然语言 Content-Language

要知道这些字段的值,若是多个,后面的会覆盖掉前面的;为了有多个值,就需要使用q=x权重的概念,该权重值的范围是[0,1]之间的数字,数值越大权重越高;多个值是由逗号分隔的,为了为值增加权重的概念,权重和值使用分号进行分隔

  • Accept:客户端可接受的媒体类型,若服务端无法匹配则会返回406错误
    • */*:全部可接受
  • Accept-Charset:客户端接受的字符集类型
    • utf-8:也可是其他类型字符集
  • Content-Type:服务端返回的实体主体的媒体类型,是MIME格式的类型;使用分号分隔字符集
    • text/html:HTML格式
    • text/plain:纯文本格式
    • text/xml:XML格式
    • image/gif:gif图片格式
    • image/jpeg:jpg和jpeg图片格式
    • image/png:png图片格式
    • application/xhtml+xml:XHTML格式
    • application/xml:XML数据格式
    • application/atom+xml:Atom XML聚合格式
    • application/json:JSON数据格式
    • application/pdf:pdf格式
    • application/msword:Word文档格式
    • application/octet-stream: 二进制流数据(如常见的文件下载)
    • application/x-www-form-urlencoded:表单默认的提交数据的格式
  • Accept-Encoding:客户端可接受的压缩方式
    • *:任意压缩格式
    • gzip:gzip压缩格式
    • deflate:deflate压缩格式
  • Content-Encoding:服务端返回主体内容的压缩方式
    • gzip:gzip压缩格式
    • deflate:deflate压缩格式
  • Accept-Language:客户端可接受的自然语音类型
    • zh-cn:中国大陆
    • zh:中文
    • en:英语
    • en-us:英语美国
  • Content-Language:服务端返回主体内容的自然语言类型
    • zh-cn:中国大陆
    • zh:中文
    • en:英语
    • en-us:英语美国

协商方式

  • 客户端驱动:客户端发起请求,服务端发送可选项列表,客户端做出选择后发送第二次请求
  • 服务端驱动:服务端检查客户端的请求头并决定提供那个版本的页面,当都不匹配时服务器会返回默认版本的页面
  • 透明协商:由缓存代理服务器来代表客户端进行协商,是非HTTP协议标准M,但是效率比较高

断点续传与多线程下载

原理

  • 请求头中增加字段Range来指定请求资源的片段,该字段的值有以下几种形式

    • bytes=0-99:请求0到99字节内容
    • bytes=-99:请求最后99个字节内容
    • bytes=99-:请求从第99到最后的内容
    • bytes=0-29,50-99:请求从0到29和50到99字节两部分的片段
  • 响应头中增加字段Content-Range来指定返回资源的片段,该字段的值与Range类似,只不过多增加了一个总大小,格式如下

    • bytes=99-/1024:返回从99字节到最后的内容,总大小为1024字节

断点续传和多线程下载的过程

断点续传是客户端主动的分片传输,而多线程是服务端主动的分片传输,原理是一致的,这里只说明断点续传

  1. 客户端请求下载一个1024字节大小的文件,已经下载了512字节
  2. 网络中断,客户端请求断点续传,在请求头中声明本次断点续传的起点,即Range: bytes=512-
  3. 服务端收到断点续传的请求,从文件的512字节部分开始传输,在响应头中声明断点续传的位置,即Content-Range: bytes=512-/1024
  4. 并且返回的HTTP状态码是206表示断点续传成功,而不是200

认证方式

Basic认证方式

  1. 客户端先发送请求,服务端返回401状态码要求用户身份认证,同时返回一个WWW-Authenticate响应头信息
  2. 用户填写用户名和密码后,浏览器会自动将用户名和密码字符串使用冒号连接后,采用base64编码,放在请求头的Authenticate字段中(该字段值的前面还需要添加Basic空格前缀)发送给服务器
  3. 认证通过后返回200状态码,失败后继续返回401

Digest认证方式

  1. 客户端先发送请求,服务端返回401状态码要求用户身份认证,同时返回一个WWW-Authenticate响应头信息,该信息中会包含一个临时质询码(就是一个随机的字符串)
  2. 用户填写用户名和密码后,浏览器会自动将用户名和密码字符串使用冒号连接后,使用临时质询码再base64编码,放在请求头的Authenticate字段中(该字段值的前面还需要添加Digest空格前缀,和临时质询码以及必要的一些信息)发送给服务器
  3. 认证通过后返回200状态码,失败后继续返回401

SSL客户端认证方式

  1. 客户端先发送请求,服务端会要求用户进行身份认证,该认证是通过表单认证,同时服务端会要求下载客户端证书
  2. 每次登入时都会将该证书以HTTP报文的方式发给服务器
  3. 验证通过后,就可以领取证书内的公开密钥,之后就可以开始HTTPS加密通信

FormBase认证方式

就是通过Cookie和Session的认证方式

Cookie与Session
  • Cookie:
    • 是一段文本信息,用来保存用户信息,主流浏览器对是以文本文件形式保存在本地
    • 客户端请求服务器时会自动将Cookie在请求头中作为一个字段发送,服务端需要在响应头中使用Set-Cookie设置带回的Cookie
  • Session:
    • Session也是用来保存用户的信息,保存在服务端,通常需要借助于Cookie来存储一个SessionID来保存用户的登入状态
    • 由于保存在服务端,通常都在内存中,必然会消耗大量的服务端资源,所以为了节省服务器资源就会将一些不活跃的Session删除掉
    • 虽然最常用的是使用Cookie来存储SessionID,但是在用户禁用Cookie时会无法使用,也可以采用其他方式,比如:
      • URL重写:在URL中的query部分增加查询SessionID的字段
      • 隐藏表单:使用隐藏表单保存SessionID
此作者没有提供个人介绍
最后更新于 2020-03-24