与HTTP协作的Web服务器
用单台虚拟主机实现多个域名
不同的域名部署在同一个服务器上,使用DNS服务解析域名后,两者访问的IP地址一样。
因此Host首部必须完整指定主机名或域名的URI
代理,网关,隧道
- 代理
是具有转发功能的应用程序。接收和发送 服务器/客户端的请求与响应。
- 不改变请求URI,直接发送给具有资源的目标服务器
- 通过代理服务器会追加Via首部字段标记出现的主机信息
- 使用代理服务器的理由: 利用缓存技术减少网络带宽的流量,组织内部针对特定网站的访问控制,获取访问日志;
缓存代理
转发服务器响应时,先将资源副本缓存在代理服务器上,当客户端再次请求时直接从代理服务器获取缓存资源。
透明代理
对报文内容不进行任何加工的代理。
- 网关
转发其他服务器通信数据的服务器。
可以使通信线路上的服务器提供非HTTP协议服务。 - 隧道
相当于中转站,保持客户端和服务器安全的连接。
隧道不会解析HTTP请求。
保存资源的缓存
- 有效期
- 缓存服务器,客户端浏览器都可以保存缓存
HTTP首部
请求报文首部: 请求行,请求首部字段,通用首部字段,实体首部字段
响应报文首部: 状态行,响应首部字段,通用首部字段,实体首部字段
问题: 重复的首部字段?
未明确规范,有些浏览器会优先处理第一次出现的首部字段,有些会处理最后出现的字段。
首部字段类型
- 通用首部字段
请求报文和响应报文都会使用的首部
首部字段名 | 说明 | 首部类型 |
---|---|---|
Cache-Control | 控制缓存的行为 如 no-cache | |
Connection | 逐跳首部,连接的管理 | Hop-by-hop 逐跳首部 |
Date | 创建报文的日期时间 | |
Pragma | 报文指令 | |
Trailer | 报文末端的首部一览 | Hop-by-hop 逐跳首部 |
Traster-Encoding | 指定报文主体的传输编码方式 | Hop-by-hop 逐跳首部 |
Upgrade | 升级为其他协议 | Hop-by-hop 逐跳首部 |
Via | 代理服务器的相关信息 | |
Warning | 错误通知 |
- 请求首部字段
从客户端向服务器端发送请求报文时使用的首部,补充了请求的附加内容,客户端信息,相应内容相关优先级等信息。
首部字段名 | 说明 | 首部类型 |
---|---|---|
Accept | 用户代理可处理的媒体类型 | |
Accept-Charset | 优先的字符集 | |
Accept-Encoding | 优先的内容编码 | |
Accept-Language | 优先的语言(自然语言,如zh,en,ja) | |
Authorization | Web认证信息 | |
Expect | 期待服务器的特定行为 | |
From | 用户的电子邮箱地址 | |
Host | 请求资源所在服务器 | |
If-Match | 比较实体标记 | |
If-Modified-Since | 比较资源的更新信息 | |
If-None-Match | 比较实体标记(与If-Match相反) | |
If-Range | 资源未更新时发送实体Byte的范围请求 | |
If-Unmodified-Since | 比较资源的更新时间(与If-Modified-Since相反) | |
Max-Forwards | 最大传输逐跳数 | |
Proxy-Authorization | 代理服务器要求客户端的认证信息 | Hop-by-hop 逐跳首部 |
Range | 实体的字节范围请求 | |
Referer | 对请求中URI的原始获取方 | |
TE | 传输编码的优先级 | Hop-by-hop 逐跳首部 |
User-Agent | HTTP客户端程序的信息 |
- 响应首部字段
从服务端向客户端返回响应报文时使用的首部,补充了响应的附加内容,也会要求客户附加额外的信息。
首部字段名 | 说明 | 首部类型 |
---|---|---|
Accept-Ranges | 是否接受字节范围请求 不接受: Accept-Ranges:none 接受: Accept-Ranges:bytes |
|
Age | 推算资源创建经过时间 | |
ETag | 资源的匹配信息 | |
Location | 令客户端重定向至指定URI | |
Proxy-Authenticate | 代理服务器对客户端的认证信息 | Hop-by-hop 逐跳首部 |
Retry-After | 对再次发起请求的时机要求 | |
Server | Http服务器的安装信息 | |
Vary | 代理服务器缓存的管理信息 | |
WWW-Authenticate | 服务器对客户端的认证信息 |
- 实体首部字段
针对请求报文和响应报文的实体部分使用的首部。
首部字段名 | 说明 |
---|---|
Allow | 资源可支持的HTTP方法,不支持返回405状态码 |
Content-Language | 实体主体适用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小(字节),对实体主体进行内容编码传输时,不能再使用Content-Length首部字段 |
Content-Loacation | 替代对应资源的URI |
Content-MD5 | 实体主体的报文摘要,检查报文主体在传输过程是否保持完整以及确认传输到达,无法确认是否被篡改 |
Content-Range | 实体主体的位置范围 |
Content-Type | 实体主体的媒体类型 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
非HTTP/1.1首部字段
不限于RFC2616中定义的47种首部字段,还有Cookie,Set-Cookie和Content-Dispostion等在其他RFC定义的首部字段
统一归纳在RFC4229
End-to-end首部和Hop-by-hop首部
HTTP首部字段将定义成缓存代理和非缓存代理的行为,分为2种类型。
- End-to-end 端到端首部
分在此类别的首部会转发给请求/响应对应的最终接受目标,且必须保存在由缓存生成的响应中,另外规定它必须被转发。 - Hop-by-hop 逐跳首部
分在此类别中的首部只对单次转发有效,通过代理或缓存后不再转发。
已在上面的表格标记哪些是逐跳首部,还有Keep-Alive 也是逐跳首部。未标记的都是端到端首部。
HTTP/1.1通用首部字段
Cache-Control
- 缓存请求指令
指令 | 参数 | 说明 |
---|---|---|
no-cache | - | 强制向源服务器再次验证 |
no-store | - | 不缓存请求或响应的任何内容 |
max-age=[秒] | 必须 | 响应的最大Age值 |
max-stale=[秒] | 可省略 | (指定时间内)接收已过期的响应 |
min-fresh=[秒] | 必须 | 期望在指定时间内的响应仍有效 |
no-transform | - | 代理不可更改媒体类型 |
only-if-cached | - | 从缓存获取资源,不重新加载响应,也不再次确认资源有效性 |
cache-extension | - | 新指令标记(token) |
- 缓存响应指令
指令 | 参数 | 说明 |
---|---|---|
oublic | - | 可向任意方提供响应的缓存 |
private | 可省略 | 仅向特定用户返回响应 |
no-cache | 可省略 | 缓存前必须先确认其有效性 |
no-store | - | 不缓存请求或响应的任何内容 |
no-transform | - | 代理不可更改媒体类型,防止缓存或代理压缩图片等类似操作 |
must-revalidate | - | 可缓存但必须再向源服务器进行确认,会忽略max-stale 指令 |
proxy-revalidate | - | 要求中间缓存服务器对缓存的响应有效性再进行确认 |
max-age=[s] | 必须 | 响应的最大Age值 |
s-maxage=[s] | 必须 | 公共缓存服务器响应的最大Age值 |
cache-extension | - | 新指令标记(token) |
-
no-cache指令
防止从缓存中返回过期的资源。
客户端请求: 不接受缓存的响应;
服务端响应: 缓存服务器不能对资源进行缓存,若指定参数值,则客户端在接收到这个被指定参数值的首部字段对应的响应报文后,不能使用缓存。 -
s-maxage指令
适用于供多位用户适用的公共缓存服务器。使用该指令,则忽略Expires及max-age指令。 -
max-age指令,Expires首部字段同时存在
应用HTTP/1.1的缓存服务器:忽略Expires,优先处理max-age
应用HTTP/1.0的缓存服务器:忽略max-age,优先处理Expires -
扩展 cache-extension token
Cache-Control:private,community="UCI"
如上,Cache-Control根本没有community这个指令,借助extension tokens实现了该指令的添加,如果缓存服务器无法理解则直接忽略。
Connection
逐跳首部。
- 控制不再转发给代理的首部字段
- 管理持久连接
HTTP/1.1 版本默认都是持久连接,因此服务器想断开连接,则指定Connection首部字段的值为Close
HTTP/1.1之前的版本都是非持久连接,因此如果想要维持持续链接,则需要指定Connection首部字段的值为Keep-Alive
Date
HTTP/1.1协议使用RFC1123规定日期时间的格式
Date: Tue,02 Jul 2012 04:40:59 GMT
之前的HTTP协议版本使用的是RFC850定义的格式
Date: Tue,02-Jul-12 04:40:59 GMT
除此之外还有一种格式:
Date: Tue Jul 02 04:40:592012
Pragma
HTTP/1.1之前版本的历史遗留字段,仅作为于HTTP/1.0的向后兼容而定义。
Pragma: no-cache
等同于Cache-Control: no-cache
Trailer
首部字段Trailer会事先说明在报文主体后记录了哪些首部字段。该首部字段可应用在HTTP/1.1版本分块传输编码时。
不知道这个首部字段有什么用?
Transfer-Encoding
规定了传输报文主体时采用的编码方式。
- chunked 数据分块传送 注意:HTTP/2 中已经不支持 chunked 这一格式
- deflate 使用deflate压缩算法zlib结构
- gzip 使用Lempel-Ziv coding编码的压缩格式
- identity 标识身份函数(e.g. no compression,nor modification )
关于这一点更详细的说明可参考HTTP 协议中的 Transfer-Encoding
分块编码相当简单,在头部加入
Transfer-Encoding: chunked
之后,就代表这个报文采用了分块编码。这时,报文中的实体需要改为用一系列分块来传输。每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF( ),也不包括分块数据结尾的 CRLF。最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。require('net').createServer(function(sock) { sock.on('data', function(data) { sock.write('HTTP/1.1 200 OK '); sock.write('Transfer-Encoding: chunked '); sock.write(' '); sock.write('b '); sock.write('01234567890 '); sock.write('5 '); sock.write('12345 '); sock.write('0 '); sock.write(' '); }); }).listen(9090, '127.0.0.1');
Upgrade
用于检测HTTP协议及其他协议是否可以使用更高版本进行通信。
使用Upgrade时还需要额外指定Connection:Upgrade,因为Upgrade仅限于客户端与邻接服务器之间。
服务器返回101状态码
Via
报文经过代理/网关时,Via首部字段追加服务器信息,然后进行转发。
- 追踪报文的转发
- 避免请求回环
- 通常与TRACE方法一起使用
Warning
由HTTP/1.0 Retry-After演变过来。告知用户一些与缓存相关的问题的警告。
警告码 | 警告内容 | 说明 |
---|---|---|
110 | Response is stale 响应已过期 | 代理返回已过期的资源 |
111 | Revalidation falied 再验证失败 | 代理再验证资源有效性失败(服务器无法到达等原因) |
112 | Disconnectiong operation 断开链接操作 | 代理与互联网被故意切断 |
113 | Heuristic expiration 试探性过期 | 响应的试用期超过24小时(有效缓存的设定时间大于24小时的情况下) |
199 | Miscellaneous warning 杂项警告 | 任意的警告内容 |
214 | Transformation applied 使用了转换 | 代理对内容编码或媒体类型等执行了某些处理时 |
299 | Miscellaneous persistent warning 持久杂项警告 | 任意的警告内容 |
请求首部字段
Accept
- 表示代理能够处理的媒体类型及优先级
- 可用q=表明优先级,范围0-1(可精确到小数点后三位)
Accept: text/html;q=0.5,*/*;q=0.8
Accept-Charset
- 表示代理能够处理的字符集及优先级
- 可用q=表明优先级,范围0-1(可精确到小数点后三位)
Accept-Charset: iso-8859-5,unicode-1-1;q=0.8
Accept-Encoding
- 表示代理能够处理的内容编码及优先级
- 也可以使用星号作为通配符,指定任意的编码格式
- 可用q=表明优先级,范围0-1(可精确到小数点后三位)
Accept-Encoding: gzip;q=0.8
Accept-Language
- 表示代理能够处理的自然语言集及优先级
- 可用q=表明优先级,范围0-1(可精确到小数点后三位)
Accept-Language: zh-cn,zh;q=0.4,en-us,en;q=0.8
Authorization
未认证,服务器返回401
Expect
告知服务器期望出现的某种特定行为,服务器无法理解则返回417,HTTP/1.1 仅支持100-continue
Host
告知服务器主机号及端口号
If-Match
告知服务器实体标记(ETag)值。服务器比较实体标记,符合才返回。
可用星号指定字段值,服务器会忽略比较。
If-Modified-Since
获取最新资源。
告知服务器期望的更新时间
如果资源更新时间早于客户端传过来的时间,则不接受请求,返回304 Not Modified响应;
如果资源更新时间晚于客户端传过来的时间,则接受请求并处理请求;
If-None-Match
告知服务器实体标记(ETag)值。服务器比较实体标记,不符合才返回。
在GET或HEAD方法使用该字段可获取最新资源。
If-Range
指定ETag值或时间和请求资源的ETag值或时间是否一致。
一致: 作为范围请求处理
不一致:返回全体资源
If-Unmodified-Since
告知服务器期望的更新时间
如果资源更新时间晚于客户端传过来的时间,则不接受请求,返回412 Precondition Failed响应;
如果资源更新时间早于客户端传过来的时间,则接受请求并处理请求;
Max-Forwards
该字段以十进制整数形式指定可经过的服务器最大数目.
作用: 请求经过N台服务器,若请求失败/无响应,可灵活使用Max-Forwards调查是在哪一台服务器发生问题。
Range
范围请求。若可以处理请求,返回状态码为206 Partial Content响应;若无法处理范围请求,则返回200 OK 及全部资源。
TE
- 表示代理能够处理的传输编码方式及优先级
- 和
Accept-Encoding
很像,但是用于传输编码 - 可用q=表明优先级,范围0-1(可精确到小数点后三位)
TE: gzip,deflate;q=0.4
在这里又提到一个新名词: 传输编码
查阅了资料:HTTP内容编码与传输编码
内容编码是在传输前进行的,一般是为了对实体主体进行压缩
传输编码是在传输的过程中进行编码,在内容编码的基础上,可以继续对实体主体进行传输编码,使其可以分块传输,也可以>不进行分块传输编码直接一次性进行完整传输
实体首部字段
Content-Length
本书中对该字段说明:表明了实体主体部分的大小(单位:字节)。由于实体主体计算方法略微复杂,因此有需要自行查阅RFC2616的4.4
HTTP 协议中的 Transfer-Encoding中对该字段说明:
浏览器通过Content-Length
的长度信息可以判断响应实体是否已结束。
如果Content-Length
比实际长度短会造成内容被阶段,如果比实体内容长,会造成pending.
但是,实体长度有时候并没有很好获得
例如实体来自于网络文件,或者由动态语言生成。这时候要想准确获取长度,只能开一个足够大的 buffer,等内容全部生成好再计算。但这样做一方面需要更大的内存开销,另一方面也会让客户端等更久。
因此我们需要一个新的机制:不依赖头部的长度信息也能知道实体的边界。即Transfer-Encoding:chunked
分块编码
为Cookie服务的首部字段
Set-Cookie
- 响应首部字段
- 开始状态管理所使用的Cookie信息
属性 | 说明 |
---|---|
NAME=VALUE | 赋予Cookie的名称和其值 |
expire=DATE | Cookie有效期(若不指定则默认为 浏览器关闭为止) |
path=PATH | 将服务器的文件目录作为Cookie的适用对象(若不指定则默认为文档所在文件目录) |
domain=域名 | 作为Cookie适用对象的域名(如果不指定默认为创建Cookie的服务器的域名) |
Secure | 仅在HTTPS安全通信才会发送Cookie |
HttpOnly | 加以限制,使cookie不能被JS脚本访问 |
Cookie
- 请求首部字段
- 服务器接收到的Cookie信息
其他首部字段
HTTP首部字段是可以自行扩展的。
X-Frame-Options
- 响应首部字段
- 用于控制网站内容在其他web网站的Frame标签内的显示问题,防止点击劫持攻击
- 可指定字段值
- DENY 拒绝
- SAMEORIGIN 仅同源域名下的页面匹配时许可
X-XSS-Protection
- 响应首部
- 针对跨站脚本攻击的一种对策
- 可指定字段值
0: 将XSS过滤设置为无效状态
1: 将XSS过滤设置为有效状态
DNT
- 请求首部
- 拒绝个人信息被收集,表示拒绝被精准广告追踪的一种方法
- 可指定字段值
0: 同意被追踪
1: 拒绝被追踪
P3P
- 响应首部
首部字段P3P属于HTTP响应首部,通过利用P3P(ThePlatform for Privacy Preferences,在线隐私偏好平台)技术,可以让Web网站上的个人隐私变成一种仅供程序可理解的形式,以达到保护用户隐私的目的。
要进行P3P的设定,需按以下操作步骤进行。
步骤1: 创建P3P隐私
步骤2: 创建P3P隐私对照文件后,保存命名在/w3c/p3p.xml
步骤3: 从P3P隐私中新建Compact policies后,输出到HTTP响应中
有关P3P的详细规范标准请参看下方链接。
●The Platform for Privacy Preferences 1.0(P3P1.0)Specification
http://www.w3.org/TR/P3P/
图解HTTP阅后笔记目录
图解HTTP(1-4章节)---阅后笔记
图解HTTP(5-6章节)---阅后笔记