[译] 那些咱们不须要的 HTTP 头信息

若是你想了解更多 http 头信息的知识,请关注 5 月 22 号安德鲁在伦敦的演讲html

http 头信息是控制缓存和浏览器处理web内容的一种重要方式。但不少时候它都被错误或冗余地使用,这不只没有达成咱们的使用目的,还增长了加载页面时的运行开销。这篇 http 头信息的系列博文中的第一篇文章,让咱们先来扒一扒那些没必要要的 http 头信息。前端

大多数开发者都了解一些 HTTP 头信息,并利用它去处理内容。如你们熟知的 Content-TypeContent-Length,它们都是通用的。但最近,Content-Security-PolicyStrict-Transport-Security 这样的头信息已经开始用于提升安全性,Link rel=preload 用于提升性能。只是极少数网站使用他们,尽管它们被浏览器普遍支持。android

与此同时,还有不少之前就有而且灰常受欢迎的头信息是不实用的。咱们可使用 HTTP 存档 来证明这一点。HTTP 存档 是由 Fastly 赞助并由 Google 运营的项目,每月使用 WebPageTest 加载 500,000 个网站并进行性能测试,结果公布在 BigQueryios

在 HTTP 存档数据中,这里列出了 30 个最受欢迎的响应头信息(基于存档中大多数网站都处理的头信息进行统计的结果),并大体说说它们多有用:nginx

Header name Requests Domains Status
date 48779277 535621 Required by protocol
content-type 47185627 533636 Usually required by browser
server 43057807 519663 Unnecessary
content-length 42388435 519118 Useful
last-modified 34424562 480294 Useful
cache-control 36490878 412943 Useful
etag 23620444 412370 Useful
content-encoding 16194121 409159 Required for compressed content
expires 29869228 360311 Unnecessary
x-powered-by 4883204 211409 Unnecessary
pragma 7641647 188784 Unnecessary
x-frame-options 3670032 105846 Unnecessary
access-control-allow-origin 11335681 103596 Useful
x-content-type-options 11071560 94590 Useful
link 1212329 87475 Useful
age 7401415 59242 Useful
x-cache 5275343 56889 Unnecessary
x-xss-protection 9773906 51810 Useful
strict-transport-security 4259121 51283 Useful
via 4020117 47102 Unnecessary
p3p 8282840 44308 Unnecessary
expect-ct 2685280 40465 Useful
content-language 334081 37927 Debatable
x-aspnet-version 676128 33473 Unnecessary
access-control-allow-credentials 2804382 30346 Useful
x-robots-tag 179177 24911 Not relevant to browsers
x-ua-compatible 489056 24811 Useful
access-control-allow-methods 1626129 20791 Useful
access-control-allow-headers 1205735 19120 Useful

咱们这里只关注那些不须要的头信息,以及说明为何不须要它们、该如何处理。git

没用的信息(server, x-powered-by, via)

你可能为你服务器软件的选择而骄傲,可是大多数人(用户)对此并不关心。而且这些头部信息可能会致使你的敏感信息泄漏进而使得你的网站受到攻击。github

Server: apache
X-Powered-By: PHP/5.1.1
Via: 1.1 varnish, 1.1 squid
复制代码

RFC7231 标准容许服务器在响应中包含 Server 头信息,识别用于服务内容的服务器软件。最多见的是 “apache” 和 “nginx”。虽然它是容许的,也不是强制的,可是对开发者和最终用户都没有太多实在乎义。然而,它是当今 web 上第三个最流行的 HTTP 响应头。web

X-Powered-By 是没有在任何标准中定义却很受欢迎的头信息,类似地,一般用于指出 web 服务器后的应用软件平台。常见的值有 “ASP.net”,“PHP” 和 “Express”,实际上它们并不提供任何好处,还占用空间。apache

更具争议的应该是 Via,当添加到经过其传递的代理来识别代理的任何代理的响应时,RFC7230 规定它是必须的。代理主机名的时候他多是有用的,但更多时候它像是一个通用标识符,如 “vegur”,“varnish”,或 “squid”。删除或者不设置这个头信息在技术上是违反规范的,可是没有浏览器对它作任何事情,因此若是你想删除它是没问题的。后端

弃用的标准(P3P, Expires, X-Frame-Options)

另外一类 http 头信息是那些在浏览器中有效果的,但不是(或者再也不是)达成效果的最佳方式。

P3P: cp="this is not a p3p policy"
Expires: Thu, 01 Dec 1994 16:00:00 GMT
X-Frame-Options: SAMEORIGIN
复制代码

P3P 是个让人好奇的东东。我对它不了解,甚至很好奇,它最多见的值竟然是 “this is not a p3p policy”。那它是,仍是不是啊?

这要追溯到试图使机器可读的隐私政策标准化,当时你们对于如何在浏览器中显示数据存在分歧,而且只有一个浏览器实现了这个 http 头信息 -- IE 浏览器。即便在 IE 浏览器中,P3P 也不会给用户带去任何视觉效果,它只须要在 iframe 中容许访问第三方cookie。有些网站甚至设置了一个不符合标准的 P3P 规则,好比上面的一个,即便这样作是不合法律规定的

不用说,读取第三方 cookie 一般是不可取的,因此若是你打算不这样作,你也不须要设置一个 P3P 头信息

Expires 受欢迎程度达到了难以想象的情况,试想下这种状况,Cache-Control 被设置为 20 年后过时。若是 Cache-Control 头信息包含 max-age 指令,那么在相同响应上的任何 Expires 头信息将被忽略。可是有大量网站同时设置了这两个信息,而且 Expires 头信息一般被设置为格林尼治时间 -- Thu, 01 Dec 1994 16:00:00。不少人这样作由于他们不但愿网站内容被缓存和复制,因此就从规范中复制这个实例日期来填充。

Screen Shot 2018-05-10 at 21.49.25

实际上咱们不必这么作。若是你设置了一个 Expires 头信息并为其设置了一个过往的时间,那么你能够这么设置,用来取代你以前的作法:

Cache-Control: no-cache, private
复制代码

一些审核你网站的工具会让你添加一个值为 “SAMEORIGIN” 的 X-Frame-Options 头信息。这告诉浏览器你拒绝被其余网站诬告,这也是预防点击攻击的一种经常使用手段。 然而,如下更一致的支持和更可靠的行为定义的方式,能够实现一样的效果:

Content-Security-Policy: frame-ancestors 'self'
复制代码

做为头信息(csp)的一部分,你还得到其余好处(稍后会详细介绍)。因此你如今可能没有 X-Frame-Options 头信息。

调试数据(X-ASPNet-Version, X-Cache)

使人惊讶的是,一些最经常使用的头信息都没有任何标准。实际上,这意味着,成千上万的网站彷佛自发地赞成以特定的方式使用特定的 http 头信息。

X-Cache: HIT
X-Request-ID: 45a336c7-1bd5-4a06-9647-c5aab6d5facf
X-ASPNet-Version: 3.2.32
X-AMZN-RequestID: 0d6e39e2-4ecb-11e8-9c2d-fa7ae01bbebc
复制代码

实际上,这些“未知”头信息并非由网站开发人员独立完成的。它们一般是受使用特定服务器框架、软件或特定供应商服务的人为因素的影响而造成的(在此示例中,最后一个头信息是常见的 AWS 头信息)。

特别地,X-Cache 实际是 Fastly 添加的(其余 CDN 也是这样作的),其余一些与 Fastly 相关的头信息,如X-Cache-HitsX-Served-By。当启用调试时,咱们添加更多头信息,如 Fastly-Debug-PathFastly-Debug-TTL

这些头信息没法被任何浏览器识别,删除它们对网页渲染没有任何影响。可是,因为这些标题可能向开发人员提供有用的信息,所以你或许要保留一些方法来告知开发者。

不能被正确识别(Pragma)

我没料到会在 2018 年写一篇关于“Pragma”头的文章,但根据咱们的 HTTP 存档数据,它竟然还排在了第 11 位。早在 1997 年,Pragma 就已经弃用了,它也历来没有打算成为响应头 —— 正如所指定的,它只有做为请求的一部分时才有意义。

Pragma: no-cache
复制代码

尽管如此,它做为一个响应头是如此被普遍使用,以致于一些浏览器也能识别它。如今,你的回应将传递一个能识别 Pragma 的缓存,而不能识别 Cache-Control 的几率很小。若是你想确保某些东西没有被缓存,你只须要 Cache-Control: no-cache, private

非浏览器的(X-Robots-Tag)

排名前 30 的头信息中有一个是非浏览器的头信息。X-Robots-Tag 用于对付网络爬虫,好比 Google 和 Bing 的机器人。由于它对浏览器没有任何意义,全部你能够在须要应对爬虫的时候才设置这个头信息。与此同时带来的影响,多是使得测试变得困难,或者是违反了搜索引擎的服务条款。

Bugs

最后,值得一提的是简单的错误。在一个请求中,Host 头信息存在是有道理的,可是若是它出如今响应中就说明极可能你的服务被错误地配置(我很想知道这是怎么产生的)。尽管如此,上文提到的 HTTP 存档仍是有 68 个网域返回了 Host 的头信息。

删除头信息

若是你的网站使用了 Fastly 的服务,那么恭喜你,使用 VCL 是删去头信息是很便捷的。你可能但愿将真正有用的调试数据保留到你的开发团队中,但将其隐藏在公共用户中,这颇有意义,你能够经过检测 cookie 或传进来 HTTP 头信息来轻松实现:

unset resp.http.Server;
unset resp.http.X-Powered-By;
unset resp.http.X-Generator;

if (!req.http.Cookie:debug && !req.http.Debug) {
  unset resp.http.X-Amzn-RequestID;
  unset resp.http.X-Cache;
}
复制代码

在本系列的下一篇文章中,我将讨论设置 HTTP 头信息的最佳作法,以及如何启用它们。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索