HTTP压缩

**HTTP 壓縮**是一種內建到網頁伺服器和網頁客戶端中以改進傳輸速度和頻寬利用率的方式。

HTTP 資料在從伺服器傳送前就已壓縮：相容的瀏覽器將在下載所需的格式前宣告支援何種方法給伺服器；不支援壓縮方法的瀏覽器將下載未經壓縮的資料。最常見的壓縮方案包括 brotil、gzip 和 Deflate，但可用方案的完整列表由 IANA 維護。此外，第三方可能開發新的方法並納入到其自身的產品，例如 Google 的面向 HTTP 共享字典壓縮（SDCH）方案就實現在 Google Chrome 瀏覽器和使用在 Google 的伺服器上。

在 HTTP 中有兩種不同的方式可以完成壓縮。在較低層級，Transfer-Encoding 頭可以指示 HTTP 訊息的有效載荷被壓縮。在較高層級，Content-Encoding 頭可以指示一個被轉碼、快取或參照的資源已壓縮。使用 Content-Encoding 的壓縮比 Transfer-Encoding 有更廣泛的支援，並且某些瀏覽器不宣告 Transfer-Encoding 壓縮以避免觸發伺服器的缺陷。

## 壓縮方案協商

在大多數情況中（不包括 SDCH），協商使用兩個步驟完成，這描述在 RFC 2616：

1. 網頁客戶端在 HTTP 請求的頭部通告其支援的壓縮方案為一個標記列表（tokens）。對於 Content-Encoding，這個列表稱作 Accept-Encoding；對於 Transfer-Encoding，該欄位被稱為 TE。

2. 如果伺服器支援一種或多種壓縮方案，輸出的資料可能用一種或多種雙方支援的方法壓縮。如果是這種情況，伺服器將在 HTTP 回應中添加一個 Content-Encoding 或 Transfer-Encoding 欄位表明使用的方案，用逗號分隔。

網頁伺服器本身沒有義務使用任何壓縮方法 —— 這取決於網頁伺服器的內部設定，並可能依賴於網站的內部架構。

在 SDCH 的情況下，完成一份字典協商也是必須的，其中可能涉及額外的步驟，比如從外部伺服器下載一個合適的字典。

## Content-Encoding 標記

伺服器和客戶端的標記（token）的官方列表由 IANA 維護，它包括：

* compress – UNIX 的「compress」程式的方法（歷史性，不推薦大多數應用使用，應該使用 gzip 或 deflate）
* deflate – 基於 deflate 演算法（定義於 RFC 1951）的壓縮，使用 zlib 資料格式（RFC 1950）封裝
* exi – W3C 高效 XML 交換
* gzip – GNU zip 格式（定義於 RFC 1952）。此方法截至 2011 年 3 月，是應用程式支援最廣泛的方法。
* identity – 不轉換內容。這是內容編碼的預設值。
* pack200-gzip – 傳輸 Java 存檔檔案的網路傳輸格式

除此之外，一些非官方或非標準化的標記也已被一些伺服器或客戶端使用：

* br – Brotli，一種新的開源壓縮演算法，專為 HTTP 內容的編碼而設計，已在 Mozilla Firefox 44 中實現，並且 Chromium 正準備實施。
* bzip2 – 基於自由格式 bzip2 的壓縮，被 lighttpd 支援。
* lzma – 基於原始 LZMA 的壓縮，在 Opera 20 中可用，elinks 使用一個編譯時選項也可啟用。
* peerdist – Microsoft 對等端內容快取和檢索
* sdch – Google 的面向 HTTP 共享字典壓縮，基於 VCDIFF（RFC 3284）；在最近的 Google Chrome、Chromium 和 Android 版本中原生支援，並被 Google 的網站支援。
* xpress - Windows 商店（Windows 8 及之後版本）的應用程式更新時使用的微軟壓縮協定。可選使用一個霍夫曼編碼的基於 LZ77 的壓縮。
* xz - 基於 LZMA2 的內容壓縮，Firefox 可使用非官方修補程式支援；mget 自從 2013 年 12 月 31 日已完整實現。

## 支援 HTTP 壓縮的伺服器

* SAP NetWeaver
* Microsoft IIS：內建或使用第三方模組
* Apache HTTP Server，通過 **mod\_deflate（頁面存檔備份，存於網際網路檔案館）** （正如其名，只支援 gzip）
* Hiawatha HTTP server：伺服器預先壓縮檔案
* Cherokee HTTP server，即時完成 gzip 和 deflate 壓縮
* Oracle iPlanet Web Server
* Zeus Web Server
* lighttpd，通過 **mod\_compress** 和較新的 **mod\_deflate**（1.5.x）
* nginx – 內建
* 基於 Tornado 的應用程式，如果「compress\_response」在應用設定中設定為 True（對 4.0 之前的版本，設定「gzip」為 True）
* Jetty Server – 內建到預設的靜態內容服務並在 servlet 過濾器組態中可用
* GeoServer
* Apache Tomcat
* IBM Websphere
* AOLserver
* Ruby Rack，通過 **Rack::Deflater** 中介軟體
* Varnish – 內建。也可配合 ESI

HTTP 中的壓縮也可以使用伺服器手稿語言（例如 PHP；或者程式語言，例如 Java）來實現。

## 阻礙使用 HTTP 壓縮的問題

2009 年 Google 工程師 Arvind Jain 和 Jason Glasgow 的文章指出，每天有超過 99 人年的時間由於使用者沒有接收到已壓縮內容而增加的頁面載入時間而浪費。這可能發生於：反病毒軟體檢查連接導致內容變為未壓縮；使用代理伺服器（網頁伺服器為保相容性而放棄壓縮）；伺服器組態不當；瀏覽器遇到問題而停止使用壓縮。Internet Explorer 6 在使用代理伺服器時會回退到使用 HTTP 1.0（沒有壓縮、管線等特性）—— 這是企業環境中的常見組態 —— 這也是主流瀏覽器最常遇到的，回落到未壓縮 HTTP 的情況。

另一個大規模部署 HTTP 壓縮遇到的問題是，**deflate** 編碼的定義：HTTP 1.1 將 **deflate** 編碼定義為將 deflate 壓縮（RFC 1951）的資料放入一個 zlib 格式的資料流（RFC 1950），而微軟伺服器和客戶端產品歷來將它實現為「原樣」（"raw"）資料流，這使其部署是不可靠的。出於此原因，部分軟體（包括 Apache HTTP Server）只實現 **gzip** 編碼。

## 安全問題

2012 年，一種對資料壓縮不利的普遍性攻擊被公布，被稱為 CRIME。CRIME 攻擊可能對大量協定產生效果，包括但不限於 TLS 以及應用層協定（例如 SPDY 或 HTTP）。只有針對 TLS 和 SPDY 的攻擊被論證，並且在瀏覽器和伺服器中得到了大幅緩解。CRIME 利用的 HTTP 壓縮沒有得到全面的緩解，即使 CRIME 的作者已經警告說，該漏洞的影響範圍可能比 SPDY 和 TLS 的壓縮更廣泛。

2013 年，涉及 HTTP 壓縮的 CRIME 攻擊新實例被發布，被稱為 BREACH。BREACH 攻擊可以在 30 秒內從 TLS 加密的網頁流量中提取登入權杖、電子郵件位址或其他敏感資訊（時間取決於要提取的位元組數），這也可能使攻擊者誘騙受害者存取惡意的網站連結。TLS 和 SSL 的所有版本都受到了 BREACH 的影響，無論使用何種加密演算法或密碼本。 不同於以往的 CRIME 實例，那些都可以通過關閉 TLS 壓縮或 SPDY 頭壓縮緩解攻擊；BREACH 利用的 HTTP 壓縮基本上不能關閉，因為幾乎所有網頁伺服器都依賴它提高與使用者的資料傳輸速度。

## 參考文獻

## 外部連結

* RFC 2616: Hypertext Transfer Protocol – HTTP/1.1
* HTTP Content-Coding Values（頁面存檔備份，存於網際網路檔案館） by Internet Assigned Numbers Authority
* Compression with lighttpd（頁面存檔備份，存於網際網路檔案館）
* Coding Horror: HTTP Compression on IIS 6.0（頁面存檔備份，存於網際網路檔案館）
* 15 Seconds: Web Site Compression at the Wayback Machine  （2011 年 7 月 16 日存檔）
* HTTP Compression: resource page by the founder of VIGOS AG, Constantin Rack
* Using HTTP Compression（頁面存檔備份，存於網際網路檔案館） by Martin Brown of Server Watch
* Using HTTP Compression in PHP（頁面存檔備份，存於網際網路檔案館）
* Dynamic and static HTTP compression with Apache httpd
* Browser HTTP Compression Test（頁面存檔備份，存於網際網路檔案館）
* Check HTTP compression（頁面存檔備份，存於網際網路檔案館）
* Check Gzip Compression Online（頁面存檔備份，存於網際網路檔案館）