[譯] 那些咱們不須要的 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前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索