📘 第六章 HTTP首部
📄 一句话概括

书里列了 47 个字段。 但一次真实的 GET 只能碰到十七个左右——47 是「规范定义了」的数量,不是「你会用到」的数量。

📝 本节和前面几节的关系

上一节分了四类,这一节把四类里的字段全部摊开。接下来的 6.3 到 6.6 会一个个细讲这 47 个。

一、47 的分部

分类 字段
通用 1/3 Cache-Control、Connection、Date
通用 2/3 Pragma、Trailer、Transfer-Encoding
通用 3/3 Upgrade、Via、Warning
请求 1/7 Accept、Accept-Charset、Accept-Encoding
请求 2/7 Accept-Language、Authorization、Expect
请求 3/7 From、Host、If-Match
请求 4/7 If-Modified-Since、If-None-Match、If-Range
请求 5/7 If-Unmodified-Since、Max-Forwards
请求 6/7 Proxy-Authorization、Range、Referer
请求 7/7 TE、User-Agent
响应 1/3 Accept-Ranges、Age、ETag
响应 2/3 Location、Proxy-Authenticate、Retry-After
响应 3/3 Server、Vary、WWW-Authenticate
实体 1/4 Allow、Content-Encoding、Content-Language
实体 2/4 Content-Length、Content-Location、Content-MD5
实体 3/4 Content-Range、Content-Type、Expires
实体 4/4 Last-Modified
这张表就是本章后半部分的地图:6.3 讲通用、6.4 讲请求、6.5 讲响应、6.6 讲实体,加起来正好四十七节。

二、实测只碰到 17 个

Demo 里发了一个带六个首部的 GET,又让服务端回了九个首部,两边合起来去重, 47 个里只出现了 17 个,占 36%。 没出现的那 30 个,基本都属于「要特定条件才出现」: | 类别 | 例子 | 什么时候才出现 | |---|---|---| | 代理专用 | Via、Max-Forwards、Proxy-Authenticate | 走代理时 | | 条件请求 | If-* 系列五个 | 有缓存副本时 | | 上传下载 | Content-Range、Content-MD5 | 断点续传、校验时 | | 内容协商 | Accept-Charset、Content-Language | 多语言站点 | | 认证 | Authorization、WWW-Authenticate | 需要登录时 | 所以「记住 47 个」是没必要的。真正该记住的是「哪一类里有什么」,剩下的用时查。

三、这个数字还会变

47 是 HTTP/1.1(1999 年)的清单。 之后新增的字段都不在这个表里:Alt-Svc、Strict-Transport-Security、Content-Security-Policy、 Forwarded、Early-Data…… 被废弃的也不在:Keep-Alive 从来没进过标准清单,Warning 在 2015 年被标记废弃, Content-MD5 因为不够安全而被 Digest 系列取代。 所以这张表要当成「1999 年的快照」,而不是「今天该知道的全部」。

四、动手 Demo:47 个字段的实测覆盖率

把书里四类的 47 个字段写成四张清单,发一次真实请求,然后把请求和响应里出现过的字段名都收进来, 逐个标注「出现/没出现」。

ALL = {
    u'通用': [u'Cache-Control', u'Connection', u'Date', ...],
    u'请求': [u'Accept', u'Accept-Charset', ..., u'User-Agent'],
    u'响应': [u'Accept-Ranges', ..., u'WWW-Authenticate'],
    u'实体': [u'Allow', ..., u'Last-Modified'],
}

hit = 0
for grp, names in ALL.items():
    got = [n for n in names if n.lower() in seen]
    hit += len(got)
    print(u'【%s首部】%d 个里出现 %d 个' % (grp, len(names), len(got)))

实跑输出:

--------------------------------------------------------------------
书里那 47 个字段,一次真跑的会话里能见到几个
--------------------------------------------------------------------
  【通用首部】9 个里出现 3 个
    Cache-Control            出现
    Connection               出现
    Date                     出现
    Pragma                   没出现
    Trailer                  没出现
    Transfer-Encoding        没出现
    Upgrade                  没出现
    Via                      没出现
    Warning                  没出现

  【请求首部】19 个里出现 7 个
    Accept                   出现
    Accept-Charset           没出现
    Accept-Encoding          出现
    Accept-Language          出现
    Authorization            没出现
    Expect                   没出现
    From                     没出现
    Host                     出现
    If-Match                 没出现
    If-Modified-Since        没出现
    If-None-Match            没出现
    If-Range                 没出现
    If-Unmodified-Since      没出现
    Max-Forwards             没出现
    Proxy-Authorization      没出现
    Range                    出现
    Referer                  出现
    TE                       没出现
    User-Agent               出现

  【响应首部】9 个里出现 4 个
    Accept-Ranges            出现
    Age                      没出现
    ETag                     出现
    Location                 没出现
    Proxy-Authenticate       没出现
    Retry-After              没出现
    Server                   出现
    Vary                     出现
    WWW-Authenticate         没出现

  【实体首部】10 个里出现 3 个
    Allow                    没出现
    Content-Encoding         没出现
    Content-Language         没出现
    Content-Length           出现
    Content-Location         没出现
    Content-MD5              没出现
    Content-Range            没出现
    Content-Type             出现
    Expires                  没出现
    Last-Modified            出现

  书里一共                   47 个
  这次跑到                   17 个(36%)
  没见到的                   30 个
  没见过的这些,基本都属于「要特定条件才出现」:
  Pragma、Trailer、Transfer-Encoding、Upgrade、Via、Warning、Accept-Charset、Authorization、Expect、From、If-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since、Max-Forwards、Proxy-Authorization、TE、Age、Location
  Proxy-Authenticate、Retry-After、WWW-Authenticate、Allow、Content-Encoding、Content-Language、Content-Location、Content-MD5、Content-Range、Expires

  47 这个数字不是「你会用到的数量」,而是「规范定义了的数量」。
  日常一次 GET 能碰到十几个;剩下那些要么是条件请求专用,
  要么是代理专用,要么是上传下载专用。
  所以别背清单,记清楚「哪一类里有什么」就够了。

通用 9 个里出现 3 个(Cache-Control、Connection、Date);请求 19 个里出现 7 个; 响应 9 个里出现 4 个;实体 10 个里出现 3 个。 合计 17 个,36%。 剩下 30 个没出现——它们的名字在输出里全列出来了,可以对照自己的项目看哪些其实用过。 顺手能发现一件事:Range 出现在请求那一栏里、Accept-Ranges 出现在响应里。 这对字段是一问一答——客户端说「我要一段」,服务端说「我支持分段」。

30 秒实验

  1. 再加一个走代理的请求(带 Via)和一个 Range 请求,看能多覆盖几个。
  2. 把服务端改成回 401 加 WWW-Authenticate,看那个字段长什么样。
  3. 想一想:为什么 Keep-Alive 不在这个 47 个里,但抓包时经常看到?

常见误区

  1. 「47 个首部要背下来」——按类记结构就行,具体名字用时查。
  2. 「不在 47 个里就不是标准字段」——很多字段由别的 RFC 定义,或者成了事实标准。
  3. 「这 47 个是今天的全部」——这是 1999 年的快照,之后新增废弃都很多。
自测三问(点开对答案) 1. 四类各有多少个,合计多少? —— 通用 9、请求 19、响应 9、实体 10,合计 47。 2. 为什么一次普通 GET 只能碰到十几个? —— 很多字段要特定条件才出现:走代理、有缓存副本、要认证、要分段传输等。 3. `Range` 和 `Accept-Ranges` 是什么关系? —— 一问一答:客户端用 Range 请求某一段,服务端用 Accept-Ranges 声明支持分段。

47 个说完了。接下来看那些不在这张表里的字段——它们同样天天在用。

相关笔记