常见的HTTP报头(头参数)
本内容摘抄自《RESTful WebServices》 中文译本附录C '常见的HTTP报头'。
原文作者:Leonard Ricbardson & Sam Ruby
翻译:徐涵、李红军、胡伟
标准报头
- Accept
类型:请求报头。
重要程度:中等。
客户端通过Accept报头告诉服务器,它希望服务器采用什么表示格式返回,有的客户端也许期望JSON,有的也许期望xml。
对于web浏览器而言,把这一信息放在HTTP报头里是个不错的主意,但是对于web服务客户端而言,不应将此作为唯一的解决方案。
- Accept-Charset
类型:请求报头。
重要程度:低。
客户端通过该报头告诉服务器,它希望服务器为表示采用什么字符集。例如有些期望UTF-8。
- Accept-Encoding
类型:请求报头。
重要程度:中等到高。
客户端通过该报头告诉服务器,可以通过compress或gzip这些众所周知的压缩算法对响应体进行压缩,从而节省宽带。它和字符集编码无关。
- Accept-Language
类型:请求报头。
重要程度:低。
客户端可以通过该报头告诉服务器,它希望为表示采用哪种人类语言。
- Accept-Ranges
类型:响应报头。
重要程度:低到中等。
服务器发送这个报头,表明它支持部分HTTP GET(partial HTTP GET)。客户端可以先发送一个HEAD请求,以便获取服务器返回的Accept-Ranges报头,然后再发送包含Range报头的GET请求,以获取资源的部分表示。
- Age
类型:响应报头。
重要程度:低。
假如响应主体不是服务器刚刚生成的,那么可以通过该报头表明它在服务器上存在多久了。这个报头通常由HTTP缓存来设置,以便让客户端知道它得到的表示可能是一个旧的副本。
- Allow
类型:响应报头。
重要程度:目前很低,可能会变高(2008年)
用于响应OPTIONS请求,以告诉客户端一个特定资源支持哪些HTTP方法。
- Authorization
类型:请求报头。
重要程度:非常高。
这个请求报头包含认证证书,例如一个按特定认证方案进行编码的用户名和密码。服务器收到包含Authorization报头的请求后,将先解码其中的证书,然后确定是否执行该请求。
理论上人们只需要Authorization这一个认证报头就够了(Proxy-Authorization是一个例外,因为它在一个不同的层次上工作),因为它是可扩展的。但是在实践中,仍有自定义认证报头的情况,比如说基于Authorization报头的X-WSSE。HTTP基本认证和HTTP摘要认证是最常见的认证方案,不过只要客户端和服务器双方均能理解,采用任何方案都可以。
- Cache-Control
类型:请求/响应报头。
重要程度:中等。
此报头用于给客户端和服务器之间的缓存(包括客户端和服务器自身的缓存)下达指示。它明确指出缓存的规则,以及何时清除缓存。
例如:
Cache-Control:max-age=36000 缓存3600秒
Cache-Control:no-cache 禁用缓存
Cache-Control:private 只能被客户单缓存不能被代理缓存
- Connection
类型:响应报头。
重要程度:低。
大多数HTTP响应是从服务器到客户端的通信。介于服务器与服务端之间的媒介(比如代理)能够查看响应,但它不以此为主要目的。不过服务器可以额外附加一些面向代理的特殊报头,而且一个代理可以附加一些面向下一个代理的特殊报头。它们把这些特殊报头的名称写在Connection报头里。这些特殊报头是针对两个机器间的TCP连接的,而不是针对服务器与客户端间的HTTP连接的,代理应该在把响应转发出去之前,先把其中的特殊报头以及Connection报头本身去掉。当然,如果它需要,可以再附加一些新的特殊报头和一个Connection报头。如果你正在编写客户端,而且不准备使用代理,那么你可能遇到的唯一一个Connection报头的值是“close”。它的意思是,服务器将在处理好本次请求之后,把TCP连接关闭。
- Content-Encoding
类型:响应报头。
重要程度:中等到高。
该报头与Accept-Encoding请求报头相对。表示服务器实际采用的是什么压缩算法。
- Content-Language
类型:响应报头。
重要程度:中等。
该报头与Accep-Language请求报头相对。表示响应主体所采用的自然语言,它可能会列出多个语言。
- Content-Length
类型:响应报头。
重要程度:高。
此响应报头给出实体主体的大小(以字节为单位)。它有两个重要用途:
1、客户端可以读取这个报头,并为读取主体实体做好准备。
2、客户端可以通过做一次HEAD请求来获知实体主体的大小,而不必真实的请求实体主体。
它可能回影响到客户端作出“是获取整个表示,还是部分表示,抑或不获取表示”的决定。
- Content-Location
类型:响应报头。
重要程度:低。
此响应报头把所请求资源的规范URI告诉客户端。跟Location报头不同的,Content-Location报头完全是信息性的,它并不要求客户端使用新的URI。
当服务为同一个资源的不同表示分配了不同的URIs时,该报头会比较有用。比如说,假如客户端想得到一个资源的”与特定表示无关“的通用版本,那么服务器就可以把该通用版本的URI在Content-Location报头中给出。所以,当你请求具有特定格式与语言的/releases/104.html.en时,服务器会在响应里把Content-Location报头的值设为/releases/104。
- Content-MD5
类型:响应报头。
重要程度:低到中等。
这是实体主体的加密校验和。客户端可以用它来检查实体主体有没有在传送过程中被损坏。由于攻击者可以同时篡改实体主体和Content-MD5报头,所以这个报头不是用于安全性目的,而只是用作错误检测的。
- Content-Range
类型:响应报头。
重要程度:低到中等。
当客户端用Range请求报头做部分GET请求时,服务器通过此响应报头告诉客户端它正在获取哪部分表示。
- Content-Type
类型:响应报头。
重要程度:非常高。
毫无疑问,这是最为著名的响应报头。这个响应报头告诉客户端实体主体是什么媒体类型。
- Date
类型:请求/响应报头。
重要程度:作为请求报头高,作为响应报头是必需的。
作为请求报头,它表示客户端发送请求的时间。作为响应报头,它表示服务器完成请求的时间。作为响应报头时,Date报头被缓存所使用。
- ETag
类型:响应报头。
重要程度:非常高。
ETag的值是一个不透明的字符串,它用于指示一个表示的特定版本。若表示发生改变,ETag也应随之改变。应尽量为GET请求的响应提供此报头。客户端将来进行条件GET时,需要用到ETag报头的值,客户端在做条件GET请求时,把ETag报头的值放在If-None-Match请求报头里,服务器可以通过If-None-Match请求报头的值判断客户端保存的表示是不是最新的,如果是最新的,服务器就不必重复发送表示,以节省时间和宽带。
条件GET请求主要是靠Last-Modified响应报头及与之相对的If-Modified-Since请求报头实现的。ETag的主要目的是提供双重保险。因为假如一个表示在一秒钟内改变两次的话,靠Last-Modified-Since是反映不出这个变化的,但ETag可以。
- Expect
类型:请求报头。
重要程度:中等。
这个报头用于LBYL请求。若服务器返回响应代码100,那么客户端可以继续发送真正的请求。若服务器返回响应代码417,那么客户端应该放弃发送真正的请求。
- Expires
类型:响应报头。
重要程度:中等。
这个报头告诉客户端(或介于服务器与客户端之间的代理),可以在一段时间内对响应(整个响应,而不仅仅是实体主体)进行缓存。条件HTTP GET需要做一次HTTP连接,
并花费一定的时间与资源。而Expires使客户端可以根本不用发送任何HTTP请求--至少在一段时间内。
- From
类型:请求报头。
重要程度:非常低。
这个报头跟电子邮件里的From字段的作用类似。它给出请求发送者的一个Email地址。由于隐私原因,这个报头在human web上根本不被采用,而在“客户端不在人类用户直接控制下“的程序上就更不用说了。你也许可以将它作为User-Agent的一个扩展。
- Host
类型:请求报头。
重要程度:必需的。
此报头包含URI的域名部分。比如url为:http://www.example.com/page.html,则URI路径是:/page.html, Host报头的值是:“www.example.com“或者”www.example.com:80“。
从客户端角度来看,可能无法理解为什么需要提供这样一个报头。由于HTTP 1.1服务器可以在一个IP地址上支持任意个域名,所以这个报头是必需的。
这一特性叫做“基于域名的虚拟主机”,它使得拥有多个域名的人不必为每个域名单独购买独立的计算机与网卡。问题是,HTTP客户端是向IP地址(而不是域名)发送请求的。所以如果没有Host报头,服务器就无法得知客户端请求的目标是哪个虚拟主机。
- If-Match
类型:请求报头。
重要程度:中等。
我们可以用其他报头来间接描述这个报头。它跟If-Unmodified-Since一样,用于给除GET以外的HTTP动作设置条件。指示If-Unmodified-Since以时间为值,而If-Match以ETag为值。
简而言之:If-Match跟If-None-Match与ETag的关系,就如同If-Unmodified-Since跟If-Modified-Since与Last-Modified的关系一样。
- If-Modified-Since
类型:请求报头。
重要程度:非常高。
这个请求报头是支持条件HTTP GET的关键。客户端把通过一次对同一URI的请求得到的Last-Modified的响应报头的值,放在本次请求的If-Modified-Since报头里。服务器可以根据比较If-Modified-Since的值与资源的最后更新日期,判断来自客户端上次请求以来资源有没有发生过改变。若资源已发生改变。也就是说条件If-Modified-Since成立,那么服务器将把新的实体主体返回客户端。若资源没有发生改变,也就是说条件If-Modified-Since不成立,那么服务器将返回响应代码304且不发送实体主体。
由于Last-Modified只能精确到1秒,所有有时仅靠If-Modified-Since会出现错误的结果。这就是为什么引入ETag与If-None-Match的原因。
- If-None-Match
类型:请求报头。
重要程度:非常高。
这个报头也用于支持条件HTTP GET。客户端把通过前一次对同一URI请求得到的ETag响应报头的值,放在本次请求的If-None-Match报头里。若ETag自上次请求以来发生变化,
则条件If-None-Match成立,服务器把新的实体主体返回给客户端。若ETag跟之前的一样,则条件不成立,服务器返回响应代码304,且不发送实体主体。
- If-Range
类型:请求报头。
重要程度:低。
此报头用于支持条件部分GET。 客户端把通过前一次请求得到的ETag或Last-Modified响应报头的值,放在本次请求的If-Range报头里。假如客户端请求的那部分表示已经变化,那么服务器就返回新的范围。否则,服务器就返回响应代码304,即便表示的其他地方发生了改变。
- If-Unmodified-Since
类型:请求报头。
重要程度:中等。
正常情况下,客户端把Last-Modified响应报头的值作为If-Modified-Since请求报头的值,以进行条件GET。这个报头也采用Last-Modified响应报头的值,但它常用于给除GET以外的HTTP动作施加条件。
举个例子:包括你在内的很多人都想修改某个资源。你获取该资源的表示,修改它,然后再用PUT请求把它发回去。但假如在发送PUT请求之前,该资源刚好被其他人修改了,
那么要么得到409,要么用你的修改把别人的修改覆盖掉。
若发送上述PUT请求时通过If-Unmodified-Since施加条件,那么如果其他人修改了该资源的话,你将得到响应代码417。你可以重新获取表示,然后修改。
该报头也可用于GET请求。
- Last-Modified
类型:响应报头。
重要程度:非常高。
此报头用于支持条件HTTP GET。它把表示的最后修改时间告诉客户端。客户端可以保存这个值,并在将来发送请求时给If-Modified-Since请求报头设置这个值。
在web应用中,Last-Modified通常取当前时间,这使得条件HTTP GET无法发挥作用。web服务器应力图做的更好一些,因为web服务器客户端常会为同一URI反复请求服务器。
- Location
类型:响应报头。
重要程度:非常高。
这是一个多功能的通用报头。它跟3XX系列(重定向)响应代码关系密切,而且很多关于HTTP重定向的混乱都源自对这个报头的错误理解。
这个报头告诉客户端应该向哪个URI请求资源,假定客户端原先不知道。也许,客户端的请求导致该资源被创建或导致该资源的URI发生变化。也许,客户端使用的是一个资源的旧URI,虽然该URI已不对应任何资源,但服务器还认识它。在这种情况下,响应代码可以是301,也可以是307或302。
有时,Location报头只是给出一个默认URI,比如用于300响应。有时,Location报头的URI不是指向客户端试图访问的资源,而是指向某个其他提供补充信息的资源,比如用于303响应。
- Max-Forwards
类型:请求报头。
重要程度:非常低。
这个报头主要跟TRACE方法配合使用。TRACE方法用于追踪处理客户端HTTP请求的代理。
- Pragma
类型:请求/响应报头。
重要程度:非常低。
此报头用于在客户端、服务器及媒介(如代理)间传达特殊指令。唯一一个官方指定是“no-cache”。不过它在HTTP 1.1中已经不使用了。可以通过Cache-Control报头设置为“no-cache”起到同样的作用。
- Proxy-Authenticate
类型:响应报头。
重要程度:低到中等。
有些客户端只能通过代理服务器来访问外部web,有些代理服务器需要认证。这个报头就是代理服务器提出认证要求的一种方式。这个报头随响应代码407一起发送。它有跟WWW-Authenticate一样的工作方式,只不过Proxy-Authenticate是代理提出认证要求,而WWW-Authenticate是web服务器提出认证要求,Proxy-Authenticate响应报头跟Proxy-Authorization请求报头相对,而WWW-Authenticate跟Authrization请求报头相对。一个请求可能需要同时提供Authorization和Proxy-Authorization报头。
- Proxy-Authorization
类型:请求报头。
重要程度:低到中等。
此报头用于通过一个要求认证的代理来发送请求。它和Authorization的工作方式类似。该报头的格式依赖于Proxy-Authenticate。
- Range
类型:请求报头。
重要程度:中等。
这个报头表明客户端试图请求一个资源的部分表示。客户端发送这个报头,一般是因为之前在下载一个大型表示的过程中中断了,现在,它回来继续下载该表示的其余部分。
此报头通常跟If-Unmodified-Since报头一起使用。假如表示自从上次请求之后发生了改变,你很可能需要重新获取整个表示。
- Referer
类型:请求报头。
重要程度:低。
当在web浏览器里点击一个链接时,浏览器将发出一个HTTP请求,而此请求的Referer报头的值就是刚刚所处那个页面的URI。
- Retry-After
类型:响应报头。
重要程度:低到中等。
这个报头通常与代表失败的响应报头一起使用,比如说413或某个5XX响应代码。它告诉客户端:虽然服务器目前无法处理你的请求,但也许一段时间之后就可以了。这个报头的值是一个时间或秒数,客户端可以在这个时间或秒数之后重试。
若服务器为每一个Retry-After报头按同样的规则来设置值得话,这只能使各个请求按原来的次序一一迟点到来--客户端仍将一遍遍地重复收到Retry-After报头。服务器应该采取某种随机机制来改变Retry-After报头,就像以太网的冲突回退周期一样。
- TE
类型:响应报头。
重要程度:低。
这个另一个“Accept”型报头。客户端通过这个报头指定它将接受的传送编码。
在实际使用中,TE只被用于传达“客户端是否理解分块编码(chunked encoding)与HTTP报尾”这一信息。
- Trailer
类型:响应报头。
重要程度:低。
当服务器采用分块传输编码(chunked transfer encoding)来发送实体主体时。它可以在实体主体的最后附加一些HTTP报头,使它们由报头成为“报尾”。服务器再把报头作为报尾发送时,需要把这些报头的名称列在Trailer报头里。
例如:Trailer:Content-Length
在服务器传送完实体主体后,它会在实体主体之后附加一个Content-Length报尾,并给出实体主体的字节数。
- Transfer-Encoding
类型:响应报头。
重要程度:低。
有时,服务器需要在尚不了解实体主体的某些重要方面的情况下发送该实体主体。服务器可以一块一块地传送该实体主体,并把Content-Length等报头放在实体主体之后。待所有块都传送结束后,服务器便可知道先前所不知道的一些信息了,它还可以把这些信息(如Content-Length和Content-MD5)作为“报尾”发送给客户端。
- Upgrade
类型:请求报头。
重要程度:非常低。
如果客户端希望使用除HTTP以外的另一种协议,它可以通过Upgrade报头通知服务器。若服务器刚好支持哪个协议,它将返回响应代码101,并立即切换到新的协议。
本报头的值不存在标准格式,但RFC2616里的Upgrade报头示例反映了HTTP设计者的一些构想:
Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/X11
- User-Agent
类型:请求报头。
重要程度:高。
服务器可以通过这个报头知道发送请求的是在哪种客户端软件。在humen web上,这是一个表示web浏览器品牌的字符串。而在programmable web上,它通常标识用来编写
客户端的HTTP库或者客户端库。
在human web 流行起来不久,服务器就开始通过User-Agent来了解对方是哪一种浏览器了,服务器会为不同的浏览器返回不同的表示。但根据User-Agent来发送不同的表示是一个槽糕的做法。检测User-Agent不但已经造成各种web浏览器之间的不兼容,还导致了User-Agent报头内部竞争。
几乎现在所有的浏览器都冒充Mozilla,因为它是第一个流行的web浏览器的内部代码名称。若不冒充为Mozilla,浏览器可能得不到它想要的表示。由的浏览器不但冒充Mozilla,还冒充MSIE,以便能够获得针对目前最流行的web浏览器(IE)的表示,少数浏览器甚至允许用户自行选择User-Agent,以欺骗服务器发送响应的表示。
不要让这种情况发生,web服务应该只通过User-Agent来收集统计数据并拒绝实现不佳的客户端的访问,而不应利用User-Agent来返回不同的表示。
- Vary
类型:响应报头。
重要程度:低到中等。
此报头用于告诉客户端,它可以修改哪些请求报头以得到一个资源的不同表示。如:Vary: Accept Accept-Language
该报头的另一个作用是告诉缓存服务器“请把资源的日文与英文表示区分开缓存”。若Vary报头的值为“*”,则表明响应不应被缓存。
- Via
类型:请求/响应报头。
重要程度:低。
在一个HTTP请求直接从客户端发往服务器、或一个响应直接从服务器发往客户端时,是没有Via报头的,当途中存在媒介(如代理)时,每个代理都会在请求或响应消息上附加一个Via报头,这样,收到该消息的接收者就可以通过查看Via报头来了解该HTTP消息经过了哪些媒介。
- Warning
类型:响应报头。
重要程度:低。
Warning报头是HTTP响应代码的补充。媒介(如缓存代理)通过插入这个报头,以告诉客户端可能存在的,不可能从响应中明显看出的问题。
跟响应代码一样,每个HTTP Warning报头都有一个3位数的值 -- “警告代码”。绝大多数警告跟缓存行为有关。如:
Warning:110 localhost:9090 Response is statle
意思是说:位于localhost:9090的缓存代理发送的是一个缓存的响应,虽然它知道该响应已经过期了。
- WWW-Authenticate
类型:响应报头。
重要程度:非常高。
这个响应代码是配合响应代码401使用的。服务器通过这个报头通知客户端,它要求客户端重新请求该URI并提供认证信息。它同时告诉客户端服务器期望采用何种认证方案。
例如:HTTP 基本认证,HTTP摘要认证,或者Digest auth或WSSE。
非标准报头
- Cookie
类型:请求报头。
重要程度:在human web上高,在pragrammable web上低。
这可能是第二著名的HTTP报头,但是它不属于HTTP标准的一部分,他是Netscape的一个扩展。
cookie是客户端与服务器之间的一个约定,即服务器通过Set-Cookie报头在客户单保存一些半持久化的状态。每当客户端得到一个cookie,它就应该在其后的每一个HTTP请求中附上这个cookie。客户端正是通过Cookie报头来传送它的所有cookie的。因为这些通过HTTP报头传送的数据不可见,随意仿佛客户端与服务器在共享一些状态。
在REST环境中,cookie的名声并不好,原因有两个,首先,它们包含“状态”常常只是一个回话ID(seesionId),它破坏了无状态性原则。第二,每当客户端接受一个cookie,它就要为其后的每个请求都附上该cookie,这就意味着,客户端不能再发送之前那些不包含cookie的请求,这也违反了无状态性原则。
如果你必须使用cookie,那么请确保你在客户端保存所有状态。否则REST的可伸缩性优点将大打折扣。
- Set-Cookie
类型:响应报头。
重要程度:在human web上高,在pragrammable web上低。
服务器通过这个报头试图在客户端的cookie中保存一些半持久化的状态。客户端应该为其后的每一请求都附带上这个cookie,直至该cookie过期。客户端可以忽略此报头,不为其后的请求设置Cookie报头,但这样做有可能得不到正确的响应。
- Slug
类型:请求报头。
重要程度:相当重要,但仅限于APP应用
Slug报头是Atom发布协议(Atom Publishing Protocol, APP)定义的,客户端在向一个集合POST二进制文档时,通过Slug报头为这个二进制文档设置标题。
关于自定义报头设计原则
自定义报头是最常见的一种扩展HTTP的方式,只要客户端与服务器就报头的含义达成一致,就可以随请求或响应发送任何希望发送的信息。
指导原则如下:
- 不要重新发明已存在的报头。
- 不要把本应放在实体主体里的信息放在报头里。
- 应遵守命名惯例。自定义报头的名称应以“X-”开头,这里“X”是“扩展(extension)”的意思。这样命名可以明确分辨一个报头是不是自定义报头,而且避免与未来的官方HTTP报头冲突。