HTTP/1.1(消息格式、连接管理、条件请求、范围请求、缓存、身份验证)

这篇文章主要是对官方文档的翻译和总结,如果有错误的地方,欢迎指正。

概述

1、HTTP(Hypertext Transfer Protocol)超文本传输协议,是一个无状态的应用层请求/响应协议。

2、一些术语:
(1)客户端(client):HTTP“客户端”是为了发送一个或多个HTTP请求而与服务器建立连接的程序(program)。
(2)服务器(server):HTTP“服务器”是接受连接以便通过发送HTTP响应来服务HTTP请求的程序。
(3)用户代理(user agent):指的是发起请求的客户端程序,比如浏览器、网页爬虫、命令行工具、电脑应用程序、手机APP等。
(4)源服务器(origin server):指可以为给定目标资源(resource)发起权威响应(authoritative responses)的程序。
(5)发送者(sender):指发送给定消息的任何实现(implementation)。
(6)接收者(recipient):指接收给定消息的任何实现(implementation)。
(7)中介(intermediary):位于user agent和origin server之间,如代理(proxy)、网关(gateway)、隧道(tunnel)。
(8)入站(inbound):用于描述与请求路由相关的方向要求,“入站”表示指向origin server。
(9)出站(outbound):用于描述与请求路由相关的方向要求,“出站”表示指向user agent。
(10)代理(proxy):是一种消息转发代理(agent),由客户端选择,通常通过本地配置规则,接收对某些类型的绝对URI(absolute URI)的请求,并尝试通过HTTP接口的转换(translation)来满足这些请求。
(11)网关(gateway):又名“反向代理”,是一个intermediary,它充当出站连接的origin server,但转换接收到的请求并将它们转发到另一台或多台服务器。
(12)隧道(tunnel):充当两个连接之间的盲中继(blind relay),而不会更改消息。
(13)资源(resource):HTTP请求的目标,每个资源都由一个URI标识。
(14)权威响应(authoritative response):是一个由目标URI标识的权威(authority)(或在其指导下)所确定的响应,是在给定 响应消息生成时的目标资源状态 下,该请求的最合适的响应。提供来自非权威来源(比如共享缓存)的响应,对于提高性能和可用性通常很有用,但仅限于来源可信任或这个不可信任的响应能安全使用的情况下。
(15)有效请求URI(effective request URI):由于request-target(在请求行中,参看“消息格式-开始行”)通常只包含user agent的目标URI的一部分,因此服务器将预定目标重建为“effective request URI”以正确地为请求提供服务。重建规则:比如,如果请求是在TLS-TCP连接中接收到,effective request URI的scheme是https,如果不是则scheme为http;如果request-target是authority-form,则effective request URI的authority部分与request-target相同,如果不是,则如果Host头部字段值非空,则authority部分与Host字段值相同……
(16)有效载荷(payload):HTTP消息的message body(如果有)用于携带该请求或响应的payload body。除非应用了传输编码(transfer coding),否则message body与payload body完全相同。(详情参看“消息格式-消息体”。)
(17)表示(representation):是旨在反映一个给定资源的过去、当前或期望状态的信息,其格式易于通过协议进行通信,由一组representation metadata和representation data的潜在无限流组成。

3、ABNF(Augmented Backus-Naur Form):
(详情参看RFC7230等官方文档Appendix-ABNF)
一种语法表示方法,比如如果想表示列表的话,语法格式是<n>#<m>element,表示至少n个至多m个元素,元素之间用“,”和OWS(optional whitespace)分隔;比如status-line = HTTP-version SP status-code SP reason-phrase CRLFstatus-code = 3DIGIT,表示status-line的格式是“HTTP-version+空格+status-code+空格+reason-phrase+回车换行”(CR (carriage return)、CRLF (CR LF)、LF (line feed)),而里面的status-code的格式是三个数字,还有HTTP-version、SP、reason-phrase、CRLF、DIGIT这些(和status-code一样)在ABNF都有定义;比如absolute-path = 1*( "/" segment ),表示absolute-path的格式是至少一个“/+segment”。
一些ABNF示例:

BWS = OWS
OWS = *( SP / HTAB )
RWS = 1*( SP / HTAB )
qdtext = HTAB / SP / "!" / %x23-5B ;#’-’[’
/ %x5D-7E ;]-’˜’
/ obs-text
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) ; VCHAR: any visible US-ASCII character, HTAB: horizontal tab, SP: space
quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
tchar = "!" / "#" / "$" / "%" / "&" / "’" / "*" / "+" / "-" / "." /
"^" / "_" / "‘" / "|" / "˜" / DIGIT / ALPHA
token = 1*tchar

消息格式

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

开始行

start-line = request-line / status-line
开始行,对于请求是请求行,对于响应是状态行。
开始行格式:
(1)请求行:

request-line  = method SP request-target SP HTTP-version CRLF
method		  = token
HTTP-version  = HTTP-name "/" DIGIT "." DIGIT
HTTP-name     = %x48.54.54.50 ; "HTTP", case-sensitive

(request-target详情参看“开始行-请求目标”)
例如:GET /user?id=123 HTTP/1.1

(2)状态行:

status-line   = HTTP-version SP status-code SP reason-phrase CRLF
status-code   = 3DIGIT
reason-phrase = *( HTAB / SP / VCHAR / obs-text )

例如:HTTP/1.1 200 OK

请求方法

1、请求方法:(详情参看RFC7231)

  • CONNECT
    CONNECT方法请求接收者建立一个到destination origin server(由request-target标识)的隧道(tunnel),如果成功,则此后将其行为限制为双向盲转发数据包,直到隧道关闭。隧道通常用于创建端到端虚拟连接(通过一个或多个代理),这个连接之后可以用TLS进行保护。CONNECT仅用于对代理的请求。接收者代理(recipient proxy)可以通过直接连接到request-target来建立隧道,或者如果配置为使用另一个代理,则通过将CONNECT请求转发到下一个入站代理来建立隧道。
  • DELETE
    DELETE方法请求origin server移除目标资源与其当前功能(functionality)之间的关联。它表达的是origin server的URI mapping上的删除操作,而不是期望之前关联的信息被删除。如果目标资源具有一个或多个current representation,它们可能会也可能不会被origin server销毁,相关联的存储可能被回收也可能不会,这完全取决于资源的性质和origin server对它的实现。
  • GET
    GET方法请求目标资源的current selected representation的传递(transfer)。
  • HEAD
    HEAD方法和GET相同,除了服务器不得在响应中发送message body。服务器应该发送相同的头部字段来响应HEAD请求,也就是如果请求是GET时会发送的头部字段,除了payload相关头部字段可以省略。
  • OPTIONS
    OPTIONS方法请求可用于目标资源的通信选项(communication options)信息(在origin server或者介于中间的intermediary)。这个方法允许客户端决定与资源相关联的选项(options)、要求(requirements),或服务器的能力(capabilities),而无需隐含资源操作(resource action)。如果OPTIONS请求以*作为request-target,则可以用来测试服务器的能力比如是否遵守HTTP/1.1;如果request-target不是*,则请求与目标资源通信时可用的options。
  • POST
    POST方法请求目标资源根据资源自身的特定语义处理请求中包含的representation。
  • PUT
    PUT方法请求目标资源的状态被创建或替换为请求消息payload中包含的representation所定义的状态。
  • TRACE
    TRACE方法请求 请求消息的远程、应用程序级环回(application-level loop-back)。请求的最终接收者应该将收到的消息(除去某些字段)(作为带有Content-Type=message/http的200响应的message body)反射回客户端。最终接收者是origin server或者第一个接收到Max-Forwards=0(在请求中)的服务器。TRACE使得客户端看到在请求链的另一端接收到的内容,并将该数据用于测试或诊断信息。

2、方法属性:
(1)安全方法:如果某个方法的定义语义(defined semantics)本质上是只读的,则认为这个方法是安全的。安全方法的合理使用不会对origin server造成任何伤害、财产损失或异常负担。比如GET、HEAD、OPTIONS、TRACE。
(2)幂等方法:该方法的多个相同的请求和单一请求在服务器上的预期效果(intended effect)一样。比如PUT、DELETE和安全方法。
(3)可缓存方法:该方法的响应允许被存储以备将来重用。比如GET、HEAD、POST。

请求目标

request-target源自(derived from)目标URI。
根据请求方法和请求是否是发给一个代理,request-target有以下四种格式:

request-target = origin-form
               / absolute-form
               / authority-form
               / asterisk-form

(1)origin-form:origin-form = absolute-path [ "?" query ]
当直接向origin server发出请求时,除了CONNECT或服务器范围(server-wide)的OPTIONS请求,客户端必须只发送目标URI的绝对路径(absolute path)和query部分作为request-target(如果目标URI的路径部分为空则用“/”作为origin-form中的path),并且需要Host头部字段。
例如从origin server请求由“http://www.example.org/where?q=now”标识的资源的一个representation,则请求如下:

GET /where?q=now HTTP/1.1
Host: www.example.org

(后面还跟着请求消息的剩余部分。)
(2)absolute-form:absolute-form = absolute-URI
当向代理发出请求时,除了CONNECT或server-wide OPTIONS请求,客户端必须发送absolute-form格式的目标URI作为request-target。(当代理被请求时,它会从有效缓存中为该请求提供服务(如果可能的话),或者代表客户端向下一个入站代理服务器或直接向request-target指示的origin server发出相同的请求。)
例如:GET http://www.example.org/pub/WWW/TheProject.html HTTP/1.1
(3)authority-form:authority-form = authority
当发出CONNECT请求以通过一个或多个代理建立隧道时,客户端必须仅发送目标URI的authority部分作为request-target。
例如:CONNECT www.example.com:80 HTTP/1.1
(4)asterisk-form:asterisk-form = "*"
asterisk-form只会用于server-wide OPTIONS请求。当客户端希望为整个服务器请求 OPTIONS时(而不是该服务器的特定命名(named)资源),客户端必须仅发送*作为request-target。
例如:OPTIONS * HTTP/1.1

状态码

(详情参看RFC7231)
status-code的第一个数字定义了响应的类别。客户端可以将无法识别的状态码当作x00,x为第一个数字。

1、1xx(Infomational)
表示请求已经收到,继续处理。这是完成请求的动作和发送最终状态码之前的临时响应,用来沟通连接状态和请求进度。
HTTP/1.0不支持1xx状态码。

  • 100(Continue)
    如果请求中包含“Expect: 100-continue”(请求中还没有包含要发送的message body),则100响应表示服务器希望收到请求的payload body。
  • 101(Switching Protocols)
    表示服务器将在同一个连接上转换成另一种协议,并且“Upgrade”头部字段会指示出新的协议。

2、2xx(Successful)
表示请求已经被成功收到、理解、接受。

  • 200(OK)
    表示请求成功。
  • 201(Created)
    表示在服务器创建了一个新资源,并且响应中的Location头部字段提供了所创建资源的标识符(identifier)。
  • 202(Accepted)
    表示请求已经被接受即将处理,但还没有处理完毕,比如DELETE方法很可能成功但是还没有执行时返回202。这个请求最终可能被执行也可能不会。
  • 203(Non-Authoritative Information)
    intermediary比如代理改变了origin server的200响应消息中随附的(enclosed)payload时返回。
  • 204(No Content)
    表示服务器已成功完成请求,并且在响应的payload body中没有附加内容要发送。
  • 205(Reset Content)
    表示服务器已经完成请求并且希望user agent重置“document view”。
  • 206(Partial Content)
    当所有的先决条件(precondition,详情参看“条件请求”)为true,目标资源也支持Range字段,指定的范围有效并且可以满足时,服务器应该返回一个带有payload的206响应,payload中包含对应于被请求的可满足的范围的一个或多个partial representation。

3、3xx(Redirection)
表示为了完成请求,需要user agent采取进一步的动作(further action)。

  • 300(Multiple Choices)
    表示目标资源有多个representation,每个都有更具体的标识符。响应中的Location表示服务器的偏好选择,user agent可以利用这个字段自动重定向。对于HEAD以外的请求方法,服务器应该在300响应中生成一个payload,其中包含一系列的representation metadata和URI reference,以供用户或者user agent选择一个最偏好的。
  • 301(Moved Permanently)
    表示目标资源已经分配了一个新的永久的URI。
  • 302(Found)
    表示目标资源临时存在于另一个不同的URI。
  • 303(See Other)
    表示服务器正在将user agent重定向到一个不同的资源(响应的Location中包含这个资源的URI),目的是为了提供一个间接的响应给原始请求。
  • 304(Not Modified)
    一般用于GET、HEAD条件请求,表示重定向客户端去使用存储的representation(也就是把它当作200响应的payload,因为如果不是条件被评估为false,本来应该返回200的)。比如If-None-Match + GET请求时,如果客户端中存储的响应中有匹配selected representation的,则recipient server会返回304。
  • 307(Temporary Redirect)
    表示目标资源临时存在于另一个不同的URI,并且user agent在执行自动重定向到那个URI时不允许改变请求方法(而301、302的自动重定向会将POST改为GET)。
  • 308(Permanent Redirect)
    在RFC7238中定义的和301等价的状态码。

4、4xx(Client Error)
表示请求中包含错误语法,或者无法被满足。

  • 400(Bad Request)
    表示服务器不能处理这个请求。请求格式不正确时返回,比如头部字段的值格式不对。
  • 401(Unauthorized)
    这种响应消息被origin server用于挑战(challenge)user agent的授权(authorization)。这个状态码表示请求无法被应用,因为它缺少目标资源的有效身份验证凭据(authentication credentials)。如果被保护资源的请求中遗漏credentials、包含无效或部分的credentials(比如密码错误),origin server应该返回401。(和407对比。)
  • 402(Payment Required)
    预留的状态码,供将来使用。
  • 403(Forbidden)
    表示服务器拒绝批准这个请求。如果服务器收到不足以获得访问权限的有效credentials,则应该返回403。
  • 404(Not Found)
    表示origin server没有找到目标资源的representation,或者有representation但是服务器不想透露它的存在。404没有指示representation的缺乏是临时的还是永久的,而410表示永久的。
  • 405(Method Not Allowed)
    表示请求方法是目标资源所不允许的。
  • 406(Not Acceptable)
    表示目标资源没有一个可以被user agent接受的current representation(根据请求中proactive negotiation相关头部字段,比如Accept-xx),并且服务器也不想提供一个默认representation。
  • 407(Proxy Authentication Required)
    这种响应消息被proxy用于挑战(challenge)client的授权(authorization)。407状态码表示为了使用proxy,客户端需要验证(authenticate)它自己。如果请求中遗漏代理凭证(proxy credentials)、包含无效或部分的proxy credentials,一个需要身份验证(authentication)的proxy应该返回407。(和401对比。)
  • 408(Request Timeout)
    表示服务器在它准备等待的时间内没有收到完整的请求消息。响应中包含“Connection: close”。
  • 409(Conflict)
    表示请求与目标资源的当前状态冲突,一般发生在PUT请求。
  • 410(Gone)
    表示对目标资源的访问不再可用,而且是永久的。
  • 411(Length Required)
    表示服务器拒绝接受没有Content-Length的请求。比如请求中有message body但没有Content-Length时返回。
  • 412(Precondition Failed)
    表示请求头部字段给出的条件被服务器评估为false。比如If-Match条件评估为false时返回。
  • 413(Payload Too Large)
    表示服务器拒绝处理这个请求,因为payload大于服务器愿意或者能够处理的范围。这个情况也许是永久的,也许是暂时的(在响应中带上Retry-After表示这个时间之后客户端可以重试)。
  • 414(URI Too Long)
    request-target太长。
  • 415(Unsupported Media Type)
    表示请求中的payload的格式(format)不被目标资源支持。格式问题可能由于Content-Type、Content-Encoding的指示,或者因为直接检验data的结果。
  • 416(Range Not Satisfiable)
    当所有的先决条件为true(指If-Match这些条件),目标资源也支持Range字段,但是指定的范围无效或者无法满足时,服务器应该返回416响应(但是也有可能返回200包含整个selected representation)。
  • 417(Expectation Failed)
    表示请求中Expect字段所指定的期望(expectation)无法被任何一个入站服务器满足。比如当Expect不是“100-continue”时返回。
  • 426(Upgrade Required)
    表示服务器拒绝用当前协议完成请求,但是也许愿意在客户端升级到另外的协议之后处理。响应中必须包含Upgrade字段。

5、5xx(Server Error)
表示服务器知道它发生错误了,或者无法执行请求的方法。

  • 500(Internal Server Error)
    表示服务器遇到了意外情况,导致无法完成请求。
  • 501(Not Implemented)
    表示服务器不支持满足请求所需的功能(functionality)。比如请求方法未实现时返回。
  • 502(Bad Gateway)
    表示充当网关或代理的服务器,在尝试满足请求时收到了它所访问的入站服务器的无效响应。所以502是由网关、代理等返回的,比如在网关等接收到响应消息格式不对时给客户端发送这个状态码响应。
  • 503(Service Unavailable)
    表示服务器当前无法处理请求,因为暂时的过载或定期维修,而这些情况可能在一段时间之后有所缓解。
  • 504(Gateway Timeout)
    表示服务器,在充当网关或代理时,没有收到它的上游服务器(为了完成请求而访问的)的及时响应。比如缓存收到“Cache-Control: only-if-cached”请求且没有合适的stored response时有可能返回504。比如缓存收到“Cache-Control: must-revalidate”请求,如果缓存因任何原因无法到达origin server,则它必须生成504响应。
  • 505(HTTP Version Not Supported)
    表示服务器不支持或者拒绝支持请求消息中所使用的HTTP major version。

头部字段

1、头部字段格式:

     header-field   = field-name ":" OWS field-value OWS

     field-name     = token
     field-value    = *( field-content / obs-fold )
     field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
     field-vchar    = VCHAR / obs-text

     obs-fold       = CRLF 1*( SP / HTAB )
                    ; obsolete line folding

2、头部字段:(详情参看RFC7231)

  • Accept
    由user agent提供,表示在响应中可接受的media type。
    格式为:
     Accept = #( media-range [ accept-params ] )
     media-range    = ( "*/*"
                      / ( type "/" "*" )
                      / ( type "/" subtype )
                      ) *( OWS ";" OWS parameter )
     accept-params  = weight *( accept-ext )
     accept-ext = OWS ";" OWS token [ "=" ( token / quoted-string ) ]
     weight = OWS ";" OWS "q=" qvalue
     qvalue = ( "0" [ "." 0*3DIGIT ] )
            / ( "1" [ "." 0*3("0") ] )
    
    例如:Accept: audio/*;q=0.2, audio/basic, text/plain;format=flowed, text/html;level=2;q=0.4,没有指出权重的表示q=1。
  • Accept-Charset
    由user agent提供,表示在文本响应内容中可接受的字符集(charset)。
    格式:Accept-Charset = 1#( ( charset / "*" ) [ weight ] )
    例如:Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
    如果请求中没有这个字段,表示接受所有charset。
  • Accept-Encoding
    由user agent提供,表示在响应中,哪些response content-codings是可接受的。
    格式:Accept-Encoding = #( codings [ weight ] )codings = content-coding / "identity" / "*",identity表示“no encoding”没有编码,*表示任何编码。
    例如:Accept-Encoding: compress;q=0.5, gzip;q=1.0, identity;q=0.5, *;q=0
    有的时候接收者不按照Accept-Encoding给发送者传数据,因为User-Agent内容表明了不能接收这种编码。(这是接收者对HTTP的具体实现决定的)。
  • Accept-Language
    由user agent提供,表示响应中的偏好语言。
    格式:Accept-Language = 1#( language-range [ weight ] )
    例如:Accept-Language: da, en-gb;q=0.8, en;q=0.7
  • Accept-Ranges
    由sever提供,表示这个目标资源支持范围请求(range requests)。
    格式:Accept-Ranges = acceptable-rangesacceptable-ranges = 1#range-unit / "none"(range-unit的定义,在“范围请求(Range Requests)”第3小节。)
    例如:Accept-Ranges: bytesAccept-Ranges: none,bytes表示目标资源支持byte-range请求,none表示目标资源不支持任何类型的范围请求。
  • Age
    这个字段表达了发送者对 自响应被origin server生成或成功验证(validate)以来 所经过的秒数的估算。这个字段的存在意味着这个响应不是由origin server(为这个请求)生成或验证的,比如这个响应消息可能是从缓存中获得的。(一些HTTP/1.0缓存可能没有实现Age。)(Age是对age的估算,响应的age的定义参看Cache-Control。)
    格式:Age = delta-secondsdelta-seconds = 1*DIGIT ;非负整数
  • Allow
    表示目标资源所准许的请求方法。
    格式:Allow = #method
    例如:Allow: GET, HEAD, PUT
  • Authorization
    当user agent收到401响应,如果它希望向origin server验证(authenticate)自己,可以在请求中包含Authorization头部字段。
    字段值由 包含user agent的身份验证(authentication)信息的 被请求资源领域(realm)的 凭证(credentials)组成。当创建字段值时,user agent应该选择它认为的最安全的auth-scheme,并且根据需要从用户那里获取credentials。
    格式:Authorization = credentialscredentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ](auth-scheme、token68、auth-param、realm参看“身份验证(Authentication)”。)
    如果一个请求已经通过身份验证并且指定了realm,则推断同一个credentials对于这个realm内的所有其他请求都有效。
  • Cache-Control
    这个字段用来指定沿着请求或者响应链的缓存指令(directive)。(请求中的指令不会用于响应,因为缓存指令是单向的。沿着请求或者响应链的所有接收者都可能使用消息中的缓存指令。)(一些HTTP/1.0缓存可能没有实现Cache-Control。)
    格式:Cache-Control = 1#cache-directivecache-directive = token [ "=" ( token / quoted-string ) ],后面的可选部分是argument(使用token或quoted-string语法)。
    例如:
    (1)Cache-Control: max-age=5,max-age既是请求指令也是响应指令(它的argument的语法是“delta-seconds”,使用token格式也就是不需要双引号),在请求中表示客户端不愿意接受age大于5的响应,在响应中表示如果这个响应的age大于5则被认为是陈旧的(stale)。(一个响应的age指的是自从它被origin server生成 或 被origin server成功验证(validate) 已经经过了多长时间。一个响应的freshness lifetime指的是它被origin server生成时的时间和过期时间之间的时间长度。stale指age超过freshness lifetime。)
    (2)Cache-Control: max-stale=10,max-stale是请求指令,表示客户端愿意接受超过freshness lifetime的响应。
    (3)Cache-Control: min-fresh=20,min-fresh是请求指令,表示客户端愿意接受 freshness lifetime >= 当前age + 20 的响应。
    (4)Cache-Control: no-cache,no-cache是请求指令(没有argument,要和第9点对比),表示一个缓存(cache)不能使用一个 没有在origin server成功验证(validate)的 stored response来满足请求。
    (5)Cache-Control: no-store,no-store既是请求指令也是响应指令,表示缓存不准(MUST NOT)存储请求和响应的任何部分(但是有些恶意缓存不一定遵守这个指令)。
    (6)Cache-Control: no-transform,no-transform既是请求指令也是响应指令,表示intermediary(不管有没有实现缓存)不准改变(transform)payload。
    (7)Cache-Control: only-if-cached,only-if-cached是请求指令,表示客户端只希望获得stored response。如果一个缓存收到这个请求,则要么用符合请求的其他约束的stored response进行响应,要么返回504。
    (8)Cache-Control: must-revalidate,must-revalidate是响应指令,表示一旦响应变成stale,则缓存不能 未经origin server成功验证(validate) 就使用这个response满足后续请求。
    (9)no-cache也属于响应指令,和第4点对比有argument(语法是“#field-name”),表示那个响应如果没有在origin server成功验证则不能被用于满足后续请求。如果argument中包含一到多个field-name,则缓存也许可以使用这个响应来满足后续请求,但是这些field-name所对应的响应头部字段 如果没有在origin server成功验证 则不能被放在给后续请求的响应中。
    (10)Cache-Control: public,public是响应指令,表示任何缓存都可以存储这个响应,即使这个响应通常不可缓存或者只在私有cache可缓存。
    (11)private是响应指令,argument语法是“#field-name”,表示这个响应消息是提供给单个用户的,共享缓存(shared cache)不准存储这个响应。argument中的field-name表示共享缓存不准存储指定的响应头部字段,但是响应消息的剩余部分可以存储。
    (12)Cache-Control: proxy-revalidate,proxy-revalidate是响应指令,含义和must-revalidate一样,区别在于proxy-revalidate不能应用于私有缓存。
    (13)Cache-Control: s-maxage=10,s-maxage是响应指令(argument的语法是“delta-seconds”),表示在共享缓存中,这个指令指定的age最大值会覆盖max-age指令或Expires头部字段所指定的age最大值。这个指令还暗含了proxy-revalidate响应指令的语义(semantics)。(和第1点max-age响应指令对比。)
    (14)如果响应中的取值是“max-age=0, must-revalidate”或“s-maxage=0”,表示这个响应如果没有在origin server重新验证(revalidate)则不能用来满足(satisfy)后续请求(subsequent request)。
    (15)Cache-Control: private, community="UCI",这是缓存扩展,community是一个cache-extension,能识别这个community缓存扩展的cache会依据这个扩展拓宽它的行为,比如“community”表示,除了私有缓存,任何仅被UCI的成员共享的cache都允许存储这个缓存。
  • Connection
    取值为当前连接的控制选项,一个代理或网关在转发消息之前要移除或者替换这个字段的连接选项。
    例如:Connection: closeConnection: upgrade
    close表示发送者在发送完请求或响应消息之后就断开连接,upgrade选项需要搭配Upgrade头部字段表示要转换的新协议。
  • Content-Encoding
    表示应用到representation的内容编码,取值有compress、deflate、gzip。
    格式是:Content-Encoding = 1#content-codingcontent-coding = token
    例如:Content-Encoding: gzip
    representation可以应用多个编码,Content-Encoding列出的是所有应用的编码,顺序为应用的先后顺序。一般是先取出representation,然后按顺序应用各种编码,然后放在message body中,如果取出的representation自带某种编码,则这个编码不用在Content-Encoding中列出。
  • Content-Language
    表示representation目标受众的自然语言,取值类型为language-tag,例如:fr、en-US、es-419、az-Arab、x-pig-latin、man-Nkoo-GN、en-CA等,en-CA表示加拿大的英语变体。
    例如:Content-Language: mi, en,表示内容的受众语言是Maori和English。Content-Language可以应用于任何media type,不只是文本类型。
  • Content-Length
    当消息中没有Transfer-Encoding头部字段时,Content-Length可以为潜在的payload body提供预期的大小(八位字节十进制数(a decimal number of octets))。
    (一个没有声明的(declared)message body长度的响应消息,message body长度由服务器关闭连接之前收到的八位字节(octets)数决定。)
    (由于无法区分成功完成的、关闭分隔的(close-delimited)消息和因网络故障而中断的部分接收到的消息,因此服务器应该尽可能生成编码()或长度分隔的(length-delimited)消息。关闭分隔(close-delimiting)特征(feature)的存在主要是为了向后兼容HTTP/1.0。)
  • Content-Location
    格式为:Content-Location = absolute-URI / partial-URI
    取值为一个URI,这个URI是消息payload中的representation对应的资源的标识符。
    Content-Location是representation metadata,如果这个URI和请求目标所代表的URI是一样的,说明payload就是那个资源在消息生成时的current representation。
    如果是会改变状态的(state-changing)方法的201响应,则Content-Location指示出payload是新创建的资源的current representation。
    总之就是,Content-Location代表payload中的representation,而这个representation不一定是effective request URI所代表的资源的representation。
  • Content-Range
    格式:
     Content-Range       = byte-content-range
                         / other-content-range
    
     byte-content-range  = bytes-unit SP
                           ( byte-range-resp / unsatisfied-range )
    
     byte-range-resp     = byte-range "/" ( complete-length / "*" )
     byte-range          = first-byte-pos "-" last-byte-pos
     unsatisfied-range   = "*/" complete-length
    
     complete-length     = 1*DIGIT
    
     other-content-range = other-range-unit SP other-range-resp
     other-range-resp    = *CHAR
     
     bytes-unit       = "bytes"
     other-range-unit = token
    
    (Range Unit的定义,在“范围请求(Range Requests)”第3小节。)
    如果一个单一的部分(part)被传输,则服务器生成206响应时,必须带上Content-Range字段,这个字段描述了响应中包含selected representation的哪个范围(range)。
    例如:(47022表示representation的完整长度。)
     HTTP/1.1 206 Partial Content
     Date: Wed, 15 Nov 1995 06:25:24 GMT
     Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
     Content-Range: bytes 21010-47021/47022
     Content-Length: 26012
     Content-Type: image/gif
    
     ... 26012 bytes of partial image data ...
    
    如果多个部分被传输,则服务器生成206响应时,必须生成"multipart/byteranges" payload,和一个Content-Type头部字段(字段中包含multipart/byteranges媒体类型和它的boundary parameter),而且在HTTP头部部分不能包含Content-Range字段(为了避免和单一部分响应混淆),但是在multipart payload的每一个body part的头部区域,必须包含Content-Range(对应于那个body part中包含的范围)。(如果selected representation的200响应会包含Content-Type,则每个body part的头部区域也应该包含相同的Content-Type。)(boundary字符串用来分隔每一个body part。)
    例如:(由于multipart/byteranges payload的各个part之间是存在开销的,比如boundary parameter的长度等,所以传输许多小的不相交的part可能比传输整个selected representation的效率还低。)
     HTTP/1.1 206 Partial Content
     Date: Wed, 15 Nov 1995 06:25:24 GMT
     Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
     Content-Length: 1741
     Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES
    
     --THIS_STRING_SEPARATES
     Content-Type: application/pdf
     Content-Range: bytes 500-999/8000
    
     ...the first range...
     --THIS_STRING_SEPARATES
     Content-Type: application/pdf
     Content-Range: bytes 7000-7999/8000
    
     ...the second range
     --THIS_STRING_SEPARATES--
    
    例如:Content-Range: bytes */1234,用于416响应,指示关于selected representation的信息比如当前长度,取值类型是unsatisfied-range。
  • Content-Type
    表示相关representation的媒体类型(media type)(payload body的内容的media type),media type定义了数据格式,和数据如何被处理(在Content-Encoding编码后的内容被解码之后)。
    字段值格式为media-type:media-type = type "/" subtype *( OWS ";" OWS parameter )parameter = token "=" ( token / quoted-string )
    例如:Content-Type: text/html;charset=utf-8Content-Type: multipart/form-dataContent-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATESContent-Type: message/http
    multipart/form-data用于请求中,表示请求中携带表单数据(form data);multipart/byteranges一般用于206响应(详情参看Content-Range的例子);message/http用于TRACE方法的响应。
  • Date
    代表消息生成的日期和时间。一般都是在响应中,请求也可以包含这个字段。
    格式:Date = HTTP-dateHTTP-date = IMF-fixdate / obs-dateIMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT
    例如:Date: Tue, 15 Nov 1994 08:12:31 GMT
  • ETag
    由origin server生成,表示selected representation的当前entity-tag。。比如表示目标资源的新representation的entity-tag,204响应中也许会有这个字段。201中的ETag沟通(communicate)新创建资源的representation的entity-tag。
    格式:
     ETag       = entity-tag
     entity-tag = [ weak ] opaque-tag
     weak       = %x57.2F ; "W/", case-sensitive
     opaque-tag = DQUOTE *etagc DQUOTE
     etagc      = %x21 / %x23-7E / obs-text
                ; VCHAR except double quotes, plus obs-text
    
    例如:ETag: "xyzzy"ETag: W/"xyzzy"ETag: "",“W/”表示之后可以使用弱(weak)比较函数进行比较。(比如强比较要求entity-tag不带有W/且字符完全匹配才是true,弱比较可以将W/去掉之后再进行字符匹配。)
    这个字段的值可以在之后的条件请求中用于If-Match字段。
  • Expect
    就是希望服务器支持的行为。
    例如:Expect: 100-continue,只发送请求行和头部字段,等收到100响应之后再发送原请求的message body部分。
  • Expires
    这个字段提供一个日期,响应在这个日期之后会被认为stale。如果响应中包含“Cache-Control+max-age”,则接收者必须忽略Expires字段;如果响应中包含“Cache-Control+s-maxage”,则共享缓存接收者必须忽略Expires字段。
    格式:Expires = HTTP-date
    例如:Expires: Thu, 01 Dec 1994 16:00:00 GMT
    (stale的定义在Cache-Control。)
  • From
    这个字段包含控制requesting user agent的人类用户的因特网电子邮件地址。
    格式:From = mailbox
    例如:From: webmaster@example.org
  • Host
    所有的HTTP/1.1请求都必须有这个字段。
    格式:Host = uri-host [ ":" port ]
    例如:Host: www.example.org
  • If-Match
    (用于条件请求的请求头部字段。)在请求方法被应用之前,origin server先使用强(strong)比较函数对字段值entity-tags进行比较,看目标资源是否有一个current representation,这个representation有一个entity-tag匹配字段值列出的entity-tags其中一个成员。
    格式:If-Match = "*" / 1#entity-tag
    例如:If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
    (和ETag一起理解。)
  • If-Modified-Since
    (用于条件请求的请求头部字段。)这个字段使得GET、HEAD请求方法有条件地执行,当selected representation的修改日期比字段值日期更近(recent)时执行。
    格式:If-Modified-Since = HTTP-date
    例如:If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
    如果是用于缓存更新,则最好是根据Last-Modified字段生成If-Modified-Since字段值,因为可能有时钟不同步等情况。而其他的使用情形,也许使用本地时钟或Date字段生成If-Modified-Since字段值。
  • If-None-Match
    这个字段使得请求方法在recipient cache或origin server上有条件地执行。接收者使用弱(weak)比较函数对entity-tag进行比较。
    格式:If-None-Match = "*" / 1#entity-tag
    例如:If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
    (和ETag一起理解。)
  • If-Range
    这个字段提供了类似于If-Match和If-Unmodified-Since的条件请求机制,但是会指导接收者在验证(validate)不匹配时忽视Range字段,从而传输新的selected representation而不是返回412。
    如果一个客户端有representation的部分内容,现在想获得整个representation的最新的内容,可以使用GET条件请求(使用If-Unmodified-Since、If-Match其中一个或两个) + Range字段,但是如果先决条件失败(因为representation被修改了),就需要客户端发起第二个请求以获得整个current representation。如果用If-Range字段代替If-Unmodified-Since和If-Match,则当representation没有改变时,只给客户端发送Range中请求的部分,否则就发送整个representation,也就是不用发起第二个请求。
    如果If-Range验证通过,则服务器一般都会去处理Range字段;如果验证不通过,则服务器会忽略Range字段。
    格式:If-Range = entity-tag / HTTP-date
    只有当对应的representation没有entity-tag,才有可能使用HTTP-date。对entity-tag的验证使用强比较(参看ETag);对HTTP-date的验证也是使用强比较,也就是必须完全相等而不是早于或等于。
  • If-Unmodified-Since
    这个字段使得请求方法有条件地执行,当selected representation的最后修改日期比字段值日期更早或相等时执行。这个字段常用于改变状态的方法,如POST、PUT、DELETE等。
    格式:If-Unmodified-Since = HTTP-date
    例如:If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
  • Last-Modified
    由origin server生成,表示selected representation最后被修改的时间。
    格式:Last-Modified = HTTP-date
    例如:Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
  • Location
    只在响应中会包含这个字段,指示一个特定资源。比如201响应中的Location代表新创建资源的标识符,301、302、303、307等也会用到Location。如果响应中有这个字段,则user agent可以自动重定向它的请求到这个URI。
    格式:Location = URI-reference
    例如:Location: /People.html#tim,如果响应是303且原请求是“http://www.example.org/~tim”,则重定向地址是“http://www.example.org/People.html#tim”。
    例如:Location: http://www.example.net/index.html,如果响应是301且原请求是“http://www.example.org/index.html#larry”,则重定向地址是“http://www.example.net/index.html#larry”,也就是保留了原始的fragment。
  • Max-Forwards
    用来限制被代理转发的次数。格式为:Max-Forwards = 1*DIGIT。仅用于TRACE和OPTIONS方法。
  • MIME-Version
    表示用了哪个MIME协议版本构造消息。
  • Pragma
    这个字段允许向后兼容HTTP/1.0缓存,主要用于请求中并使用“no-cache”。
    格式:Pragma = 1#pragma-directivepragma-directive = "no-cache" / extension-pragmaextension-pragma = token [ "=" ( token / quoted-string ) ]
    例如:
     GET / HTTP/1.1
     Host: www.example.com
     Cache-Control: max-age=30
     Pragma: no-cache
    
    表示限制HTTP/1.1缓存提供一个age不大于30的响应,同时,阻止不能理解Cache-Control的实现(implementation)提供cached response。
  • Proxy-Authenticate
    这个字段包含至少一个挑战(challenge),这些challenge指示了适用于 effective request URI的proxy 的身份验证方案(authentication scheme)和参数(parameter)。可用于407响应,包含适用于 被请求资源的proxy 的challenge。
    格式:Proxy-Authenticate = 1#challengechallenge = auth-scheme [ 1*SP ( token68 / #auth-param ) ](auth-scheme、token68、auth-param参看“身份验证(Authentication)”第2点。)
  • Proxy-Authorization
    这个字段允许客户端向需要身份验证(authentication)的proxy证明自己的身份(identify itself)。。当client收到407响应,如果它希望向proxy验证(authenticate)自己,可以在请求中包含Proxy-Authorization头部字段。
    字段值由包含客户端的身份验证(authentication)信息的凭证(credentials)组成,这些credentials用于proxy、被请求资源领域(realm)。当创建字段值时,user agent应该选择它认为的最安全的auth-scheme,并且根据需要从用户那里获取credentials。
    格式:Proxy-Authorization = credentialscredentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ](auth-scheme、token68、auth-param参看“身份验证(Authentication)”第2点。)
    例如:Proxy-Authorization: basic aGVsbG86d29ybGQ=
    与Authorization不同,Proxy-Authorization仅适用于下一个入站代理,这个proxy之前使用Proxy-Authenticate要求身份验证。
  • Range
    用于请求selected representation data的子范围(subrange),仅支持GET方法。这个字段的检测,在先决条件头部字段之后,因此,如果一个GET条件请求会返回304响应,则Range字段会被忽略。
    格式:
    Range = byte-ranges-specifier / other-ranges-specifier
    
    other-ranges-specifier = other-range-unit "=" other-range-set
    other-range-set = 1*VCHAR
    
    byte-ranges-specifier = bytes-unit "=" byte-range-set
    byte-range-set  = 1#( byte-range-spec / suffix-byte-range-spec )
    byte-range-spec = first-byte-pos "-" [ last-byte-pos ]
    first-byte-pos	= 1*DIGIT
    last-byte-pos   = 1*DIGIT
    suffix-byte-range-spec = "-" suffix-length
    suffix-length = 1*DIGIT
    
    bytes-unit       = "bytes"
    other-range-unit = token
    
    (Range Unit的定义,在“范围请求(Range Requests)”第3小节。)
    例如:Range: bytes=0-499Range: bytes=9500-Range: bytes=0-0,-1。如果缺少last-byte-pos或者它的值大于等于representation data的当前长度,则表示representation的剩余部分。suffix-byte-range-spec表示请求最后几个字节。
  • Referer
    这个字段允许user agent指定 某个资源的URI引用(URI reference)(当前请求的目标URI就是从这个资源中获得的)。
    格式:Referer = absolute-URI / partial-URI
    例如:Referer: http://www.example.org/hypertext/Overview.htmlReferer: about:blank,当没有合适的引用URI(referring URI)时使用“about:blank”。
  • Retry-After
    由服务器发送,表示user agent在发起后续请求之前应该等待的时间。比如返回413响应时有可能带有这个字段,表明这个情况是暂时的,字段值是时间,表示客户端在这个时间之后可以重试。
    格式:Retry-After = HTTP-date / delay-seconds
    例如:Retry-After: Fri, 31 Dec 1999 23:59:59 GMTRetry-After: 120
  • Server
    这个字段包含origin server用来处理请求的软件的相关信息,这个信息可以给客户端用来定制请求以避免特定的服务器限制、用于关于服务器或操作系统使用的分析等。origin server可以在它的响应中包含这个字段。
    格式:Server = product *( RWS ( product / comment ) )
    字段值包含一个或多个产品标识符,这些一起标识了origin server软件和它的重要子产品。
    例如:Server: CERN/3.0 libwww/2.17
    (Server字段描述和User-Agent有点类似。)
  • TE
    例如:TE: deflateTE: trailers, deflate;q=0.5
    在请求消息中的这个字段,表示客户端接受哪些传输编码(transfer coding)(用于响应消息的payload body),所以这个字段的取值有compress、deflate、gzip等(和Transfer-Encoding字段取值一样,但没有chunked,因为HTTP1.1接收者都可以接受这个编码),取值trailers则表示客户端接受在chunked编码中包含trailer字段(详情参看chunked-body的具体格式),q=0.5表示deflate的接受优先级权重。
  • Trailer
    表示chunked transfer coding的trailer字段包含哪些字段名,这些字段名也是头部字段名。
  • Transfer-Encoding
    例如:Transfer-Encoding: gzip, chunked
    这个字段列出了 已经或将要应用于payload body以形成message body的 传输编码序列(sequence)所对应的传输编码名称。这个字段是在HTTP/1.1版本添加的。
    取值有chunked、compress、deflate、gzip等。
  • Upgrade
    表示邀请接收方在同一个连接上转换成其他协议,字段值包含一系列协议,按偏好的降序排列。但是接收方不一定会按要求转换协议,也不一定按照偏好顺序选择协议。
    格式:
     Upgrade          = 1#protocol
     protocol         = protocol-name ["/" protocol-version]
     protocol-name    = token
     protocol-version = token
    
    例如:Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
  • User-Agent
    这个字段包含生成请求的user agent的信息,这个信息可以给服务器用来定制响应以避免特定的user agent限制、用于有关浏览器或操作系统使用的分析等。每个user agent都应该发送这个字段,除非特别配置说不需要。
    格式:User-Agent = product *( RWS ( product / comment ) )product = token ["/" product-version]product-version = token
    字段值包含一个或多个产品标识符,这些一起标识了user agent软件和它的重要子产品。
    例如:User-Agent: CERN-LineMode/2.15 libwww/2.17b3
  • Vary
    用于响应中,描述了请求消息的哪些部分,会影响origin server的 为了选择和表示这个响应的 处理。比如一般用于主动协商(proactive negotiation)的响应,表明请求消息的哪些部分被用于选择算法(选择最好的响应representation)。
    格式:Vary = "*" / 1#field-name
    例如:Vary: accept-encoding, accept-language
  • Via
    Via指的是客户端和服务器之间经过的代理或网关,是代理等接收到请求或响应消息之后转发消息之前,在Via字段值中拼接上自己接收到这个消息所用的协议和主机名。
    格式:
     Via = 1#( received-protocol RWS received-by [ RWS comment ] )
     received-protocol = [ protocol-name "/" ] protocol-version
     received-by       = ( uri-host [ ":" port ] ) / pseudonym
     pseudonym         = token
    
    例如:Via: 1.0 fred, 1.1 p.example.net
    如果协议名是HTTP则可以省略,所以Via的第一个值是HTTP/1.0,fred是接收这个请求的第一个intermediary的假名,p.example.net是第二个intermediary的主机名。假名一般用于内部网络,为了不让外部网络通过Via知道主机名所以用假名。
  • Warning
    这个字段用来携带 有关消息的状态或转换(transformation)的 额外信息,因为这些信息无法反映在状态码中。
    格式:
     Warning       = 1#warning-value
     warning-value = warn-code SP warn-agent SP warn-text
                                           [ SP warn-date ]
     warn-code  = 3DIGIT
     warn-agent = ( uri-host [ ":" port ] ) / pseudonym
                     ; the name or pseudonym of the server adding
                     ; the Warning header field, for use in debugging
                     ; a single "-" is recommended when agent unknown
     warn-text  = quoted-string
     warn-date  = DQUOTE HTTP-date DQUOTE
    
    例如:
     HTTP/1.1 200 OK
     Date: Sat, 25 Aug 2012 23:34:45 GMT
     Warning: 112 - "network down" "Sat, 25 Aug 2012 23:34:45 GMT"
    
    Warning: 110 - "Response is Stale"Warning: 111 - "Revalidation Failed"Warning: 112 - "Disconnected Operation"Warning: 113 - "Heuristic Expiration"Warning: 199 - "Miscellaneous Warning"Warning: 214 - "Transformation Applied"Warning: 299 - "Miscellaneous Persistent Warning"
    接收到一或多个Warning字段的user agent,应该按照这些Warning在响应中出现的顺序,尽可能多地将它们通知给用户。
    (1)如果代理改变(transform)了payload,则需要加上Warning字段。(2)一个缓存如果启发式地选择了一个大于24h的freshness lifetime并且响应的age大于24h,则它应该生成113Warning。(3)当缓存发送陈旧的响应(stale response)时,应该在响应中生成带有110警告码的Warning字段。(4)如果缓存不能联系上origin server或者无法找到一个转发路径,此时缓存可以发送陈旧的响应,并且响应中生成带有112警告码的Warning字段。
    (age、freshness lifetime、stale的定义参看Cache-Control字段。)
  • WWW-Authenticate
    表示适用于目标资源的身份验证方案(authentication scheme)和参数(parameter)。可用于401响应,包含适用于被请求资源的challenge;其他响应消息如果包含这个字段,则表示提供凭证(credentials)或不同的credentials会影响response。
    格式:
    WWW-Authenticate = 1#challenge
    
    challenge 	   = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
    auth-scheme    = token
    auth-param     = token BWS "=" BWS ( token / quoted-string )
    token68        = 1*( ALPHA / DIGIT /
                          "-" / "." / "_" / "~" / "+" / "/" ) *"="
    
    例如:WWW-Authenticate: Newauth realm="apps", type=1, title="Login to \"apps\"", Basic realm="simple"(realm的含义,在“身份验证(Authentication)”第4点。)

消息体

1、消息体格式:message-body = *OCTET
2、HTTP消息的message body(如果有)被用于携带该请求或响应的payload body。除非应用了传输编码(transfer coding),否则message body与payload body相同。
3、请求中message body的存在由Content-Length或Transfer-Encoding头部字段预示(signal)。
4、响应中message body的存在取决于(depends on)它响应的请求方法和响应状态码。比如HEAD请求的响应不包含message body,CONNECT请求的2xx响应也没有message body,1xx、204、304响应不包含message body。所有其他响应都包含message body,尽管body的长度可能为0。

连接管理

1、连接管理包括维护当前连接状态、建立新连接或重用已存在的连接、处理连接上接收到的消息、检测连接错误、关闭每个连接等。

2、持久连接(persistent connection):
(1)HTTP/1.1默认是使用持久连接的,也就是多个请求和响应可以通过同一个连接传输。
(2)如果头部字段设置了“Connection: close”,则会在当前请求-响应对之后断开连接,也就是这个连接不是持久性的。
(3)如果是HTTP/1.0,并且设置了头部字段keep-alive,并且不是一个发给代理的请求,则这个连接是持久性的。
(4)持久连接中发送的所有消息都必须有一个自定义(self-defined)消息长度(即不是由连接的关闭定义的)。服务器必须读取整个请求消息体(the entire request message body)或在发送响应后关闭连接,否则持久连接上的剩余数据将被误解为下一个请求。客户端也会有类似的问题。

3、连接关闭:
(1)服务器通常会有一些超时值,超过该值则服务器将不再保持(maintain)非活动(inactive)连接。
(2)Connection头部字段的“close”连接选项(connection option):

  • 请求或响应头部字段中的“Connection: close”表示发送者将在当前请求/响应完成后关闭连接。
  • 发送“close”连接选项的客户端不得在该连接上发送进一步(further)的请求(在包含“close”的请求之后),并且必须在读取与此请求对应的最终响应消息后关闭连接。
  • 收到“close”连接选项的服务器必须在它向包含“close”的请求发送最终(final)响应后启动(initiate)连接的关闭。服务器应该在该连接的最终(final)响应中发送一个“close”连接选项。服务器不得处理在该连接上收到的任何进一步请求。
  • 发送“close”连接选项的服务器必须在发送包含“close”的响应后启动连接的关闭。
  • 收到“close”连接选项的客户端必须停止在该连接上发送请求并在读取包含“close”的响应消息后关闭连接。
  • 为了避免TCP重置问题,服务器通常会分阶段关闭连接。首先,服务器通过仅关闭读/写连接的写端来执行半关闭(half-close)。然后服务器继续从连接中读取数据,直到它收到客户端的相应关闭,或者直到服务器合理地确定它自己的TCP堆栈已收到客户端对包含服务器最后(last)响应的数据包的确认。最后,服务器完全关闭连接。

(3)连接可以随时关闭,有意或无意(without intention)。当一个入站连接被过早关闭时,如果所有这些请求都具有幂等方法,则客户端可能会打开一个新连接并自动重新传输中止的请求序列(sequence)。
(4)客户端、服务器或代理可以随时关闭传输(transport)连接。例如,客户端可能在服务器决定关闭“空闲(idle)”连接的同时开始发送新请求。
(5)如果客户端看到一个响应,这个响应表明服务器不希望接收message body并正在关闭连接,客户端应该立即停止传输body并关闭它这边的连接(its side of the connection)。
(6)在HTTP/1.0中,每个连接都由客户端在请求之前建立并在发送响应后由服务器关闭。

条件请求(Conditional Requests)

1、这种HTTP请求包含一个或多个头部字段(比如If-Match、If-None-Match、If-Modified-Since、If-Unmodified-Since),用来指示在将方法语义应用到目标资源之前应该检测的先决条件(precondition)。
2、相关状态码有:304。
3、验证器(validator):HTTP1.1的说明书(specification)定义了两种常用于观察资源状态和测试先决条件的元数据(metadata)形式(form):修改日期(modification dates)和不透明实体标签(opaque entity tags)。资源元数据值在先决条件中使用时被称为“验证器”(is referred to as a “validator”)。

范围请求(Range Requests)

1、HTTP客户端经常遇到数据传输中断的情况,比如因为请求被取消或者连接被断开。当客户端已经存储了部分representation,它会希望在后续请求中请求那个representation的剩余部分,而不是传输整个representation。同样地,本地存储有限的设备可以只请求一个很大的representation的子集(subset),比如一个非常大的document的single page。

2、范围请求是一个可选的HTTP特征(feature),如果一个接收者没有实现这个特征,或者目标资源不支持范围请求,可以将这个请求当作标准的GET请求进行响应。而如果是部分响应,会带有206状态码。

3、依靠representation的media type的内在结构,一个representation可以根据各种结构单元(structural unit)划分为子范围(subrange)。这个“range unit”可以被用在Accept-Ranges(响应头部字段)中来通告对范围请求的支持,还可以用在Range(请求头部字段)中指示representation的哪一部分被请求,用在Content-Range中描述representation的哪一部分被传输。
(1)范围单元(Range Unit):由于representation data是以八位字节序列放在payload中传输,所以byte range是任何通过HTTP传输的representation的有意义子结构。“bytes”(一种range unit)用于表达 数据的八位字节序列的 子范围。
Range Unit的格式:

range-unit       = bytes-unit / other-range-unit
other-range-unit = token
bytes-unit       = "bytes"

IANA已经注册的range unit有bytes、none。bytes表示一系列octet(八位字节)。none表示不支持范围,是Accept-Ranges的取值之一。
(2)用到range-unit的头部字段有:Accept-Ranges。(详情参看“消息格式-头部字段”。)
(3)范围请求用到的头部字段有:Range、If-Range。(详情参看“消息格式-头部字段”。)
4、相关状态码:206、416。(详情参看“消息格式-开始行-状态码”。)
5、响应中的头部字段:Content-Range。(详情参看“消息格式-头部字段”。)
6、如果连接被过早地关闭,或者请求使用了Range说明(Range specifications),则响应可能只传输了representation的子范围(subrange)。
(1)如果收到了多个部分响应(partial responses),则客户端可以将这些响应组合到一个更大的连续的范围。比如,如果最近的响应是206,并且匹配的已经存储的响应中至少有一个是200,则组合后的响应(combined response)的头部字段由最近200响应的头部字段组成。
(2)combined response的message body由 新响应和每个选定响应中的 partial content ranges的并集(union)组成。
(3)如果union包含representation的整个范围,则客户端必须将combined response当作(包含反映完整(complete)长度的Content-Length头部字段的)完整的(complete)200响应来处理。如果不包含整个范围,则客户端必须将连续的ranges的集合,当作不完整(incomplete)的200响应处理当combined response是representation的前缀(prefix)时,或者当作包含一个multipart/byteranges body的单一(single)206响应,或者当作多个(multiple)206响应而每一个都带有一个连续的范围(由Content-Range指示)。

缓存(Caching)

1、HTTP cache指的是响应消息的本地存储,和控制这些消息的存储(storage)、检索(retrieval)、删除(deletion)的子系统。
2、一个缓存(cache)会存储可缓存的(cacheable)响应,这样可以减少未来等效请求的响应时间和网络带宽消耗。任何客户端、服务器都可能使用缓存,代理也可能实现缓存。
3、(1)一个共享的缓存指的是存储了可以被多个用户重用的响应的cache。共享缓存通常被部署为intermediary的一部分。(2)一个私有的缓存,专供单个用户使用,一般情况被部署为user agent的一个组件。
4、当没有要求(requirement)或本地配置阻止重用已经缓存的响应,重用是默认行为。
5、每一个缓存条目(cache entry)都由一个缓存键(cache key)和一或多个HTTP响应组成。以下列出的都可能被缓存:GET请求的200响应、永久的重定向、负面结果比如404、不完整的结果比如206、其他除GET外的方法响应。缓存键可能由请求方法和目标URI组成,也可能只由URI组成。当请求目标受内容协商(content negotiation)影响时,缓存条目由多个存储响应(stored response)组成,每个响应由二级键(secondary key)进行区分。
6、缓存中可能存储着不完整的响应(比如206响应),通过发起随后的范围请求 和 将成功响应与已经存储的entry组合,可以使不完整响应完整。
7、缓存可能会将同一个representation的几个range组合进一个单一stored response,然后重用这个response来满足后续请求。
8、如果没有可用的选定响应(selected response),则缓存(cache)无法满足提出的请求(the presented request.)。通常,这个请求会被转发(forward)到origin server(放在一个请求中,可能是条件请求)。
9、验证(Validation)
(1)当缓存对请求的URI有一到多个存储的响应但是却无法提供它们(比如因为这些响应不是fresh的(fresh指age不超过freshness lifetime)),此时缓存可以在转发的请求中使用条件请求机制,给下一个入站服务器一个机会去选择要使用的有效存储响应或者用新响应替换存储响应。这个过程称为验证或重新验证存储响应(stored response)。
(age、freshness lifetime的定义参看Cache-Control字段。)(freshness只用于缓存操作,不能用来强制user agent刷新显示或重载资源。)
(2)缓存所发送的条件请求包含先决条件头部字段,字段中的数据来自存储响应,接收者会比较这些数据以决定一个存储的响应是否和资源的current representation相等。比如条件请求中包含If-Modified-Since字段,字段值来自Last-Modified字段;比如ETag字段中的值(这些entity-tag代表相应的存储响应)可以用于If-None-Match进行响应验证(response validation)。
(3)缓存也可以作为条件请求的接收者,但是有些字段不适用于缓存,比如If-Match和If-Unmodified-Since。而If-None-Match请求可以被缓存响应比如条件为false则返回304。如果缓存接收者(cache recipient)接收到If-Modified-Since请求且selected stored response的Last-Modified字段值早于或等于If-Modified-Since字段值,则缓存接收者应该生成一个304响应。
(4)当缓存收到验证的响应时,会用这些响应刷新stored response,比如收到304响应且响应中包含强验证器(strong validator),这个验证器标识了哪些stored response要用304响应中提供的信息进行更新。如果representation body的传输是不希望的,即使它已经改变,则可以通过HEAD刷新响应。比如当缓存对给定的请求目标发出一个入站HEAD请求并收到200响应时,这个缓存应该对每一个它存储的GET响应进行更新或者使之失效(invalidate)(这些响应本该被选中去响应那个请求的)。
(5)当缓存收到PUT、POST、DELETE等非安全方法的非错误状态码(如2xx、3xx)的响应时,缓存必须将effective Request URI(也许还包括Location中的URI、Content-Location中的URI)所关联的所有stored responses,移除,或者将它们标记为无效并且在它们可以被发送以响应后续请求(subsequent request)之前需要强制验证(mandatory validation)。
10、一个请求可能会经过(travel through)好几个缓存(cache)。
11、与缓存相关的头部字段:Age、Cache-Control、Expires、Pragma、Warning。(详情参看“消息格式-头部字段”。)

身份验证(Authentication)

1、HTTP通过一组可扩展的挑战-响应(challenge-response)身份验证(authentication)方案(scheme),提供了用于访问控制(access control)和身份验证(authentication)的通用框架,服务器可以使用它来challenge客户端请求,客户端可以使用它来提供身份验证(authentication)信息。
2、一些ABNF定义:

	 auth-scheme    = token
     auth-param     = token BWS "=" BWS ( token / quoted-string )
     token68        = 1*( ALPHA / DIGIT /
                          "-" / "." / "_" / "~" / "+" / "/" ) *"="
	 challenge   = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
	 credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]

3、HTTP不会约束应用程序去使用这个简单的challenge-response框架进行访问身份验证(access authentication)。可以使用其他的机制,比如传输层的身份验证(authentication)、通过消息封装、使用额外的头部字段指定身份验证(authentication)信息。
4、保护空间(Protection Space):
(1)realm(领域):是一个身份验证参数(authentication parameter),用来指定保护范围(scope)。
(2)protection space:由被访问服务器的规范根URI(canonical root URI)(也就是effective request URI的authority和scheme) 以及 realm的值 共同定义。
(3)这些realm将服务器上的受保护资源划分成一组保护空间,每个保护空间都有自己的身份验证方案(authentication scheme)、授权数据库(authorization database)。
(4)protection space确定可以自动应用凭证(credentials)的域(domain)。如果之前的请求已经被授权(authorize),则user agent可以 在一段时间内 为那个保护空间(protection space)中的所有其他请求 重用同一个credentials(时间由身份验证方案(authentication scheme)、参数(parameters)、用户偏好决定)。
5、安全性考虑:参看RFC7235“Security Considerations”章节。

HTTP/1.1 和 HTTP/1.0的区别

1、HTTP/1.1支持Host头部字段,如果HTTP/1.1请求中缺少这个字段会报告错误。
2、HTTP/1.1接受绝对URI(absolute URIs)。
3、HTTP/1.0会假定IP地址和服务器之间的一对一关系。
4、HTTP/1.1引入Transfer-Encoding头部字段。
5、连接管理的区别。
6、一些HTTP/1.0缓存可能没有实现Cache-Control、Age。

安全相关

直接查看官方文档“Security Considerations”章节。

参考文档

1、(RFC7230) Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
2、(RFC7231) Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
3、(RFC7232) Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests
4、(RFC7233) Hypertext Transfer Protocol (HTTP/1.1): Range Requests
5、(RFC7234) Hypertext Transfer Protocol (HTTP/1.1): Caching
6、(RFC7235) Hypertext Transfer Protocol (HTTP/1.1): Authentication

  • 0
    点赞
  • 1
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页
评论

打赏作者

rccrx

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值