Tidak suka iklan? Pergi Bebas Iklan Hari ini

gzip, Brotli, Zstd Pengompresan HTTP untuk Pengembang yang Menetapkan content-encoding: identity secara Accidental

Diperbarui pada

Cara kerja negosiasi kompresi HTTP (Accept-Encoding / Content-Encoding), perbandingan sampingan gzip, Brotli, dan Zstd, cara memverifikasi kompresi benar-benar berjalan dengan curl, dan empat konfigurasi salah yang secara diam-diam menonaktifkannya.

gzip, Brotli, Zstd: Kompresi HTTP untuk Pengembang yang Menetapkan content-encoding: identity secara Kesalahan 1
IKLAN · HAPUS?

Konfigurasi nginx Anda memiliki gzip on;. Aplikasi Anda mengembalikan JSON. Isi respons masih 35KB tanpa kompresi. Tidak ada kesalahan, tidak ada peringatan — kompresi hanya terjadi secara diam-diam.

Ini biasanya merupakan salah satu dari empat konfigurasi yang salah. Namun terlebih dahulu: bagaimana proses negosiasi sebenarnya bekerja.

Cara Negosiasi Kompresi HTTP Bekerja

Dua header, tidak ada lagi. Klien mengumumkan apa yang dapat didekompresi dalam Accept-Encoding. Server memilih algoritma, mengkomprimasi isi, dan menyatakan pilihan tersebut dalam Content-Encoding:

GET /api/data HTTP/1.1
Host: example.com
Accept-Encoding: gzip, deflate, br, zstd
HTTP/1.1 200 OK
Content-Type: application/json
Content-Encoding: br
Vary: Accept-Encoding

Itu Vary: Accept-Encoding header adalah wajib jika Anda peduli tentang keakuratan caching di CDN. Tanpa header ini, CDN mungkin menyimpan respons yang dikompresi dengan Brotli dan menyajikannya kepada klien yang hanya mengumumkan gzip di dalam Accept-Encoding. Klien tersebut kemudian mencoba mendekompresi Brotli sebagai gzip dan mendapatkan data yang rusak. nginx akan menambahkan ini secara otomatis. gzip_vary on; secara teknis valid — artinya "tidak ada enkoding" — tetapi tidak ada yang secara eksplisit mengatur ini. Mode kegagalan sebenarnya adalah sebaliknya: tidak ada header

Content-Encoding: identity secara keseluruhan ketika Anda mengharapkan satu. Content-Encoding Verifikasi Kompresi Benar-Benar Berfungsi

Sebelum memperbaiki konfigurasi, pastikan masalahnya:

mengirimkan

# Check headers only
curl -sI -H "Accept-Encoding: gzip, br, zstd" https://example.com/api/data   | grep -i "content-encoding\|vary"

# Compare compressed vs uncompressed size
curl -so /dev/null -w "uncompressed: %{size_download} bytes
" https://example.com/api/data
curl -so /dev/null --compressed -w "compressed:   %{size_download} bytes
" https://example.com/api/data

--compressed secara otomatis dan mendekompresi respons. Jika kedua angka tersebut sesuai, maka kompresi tidak berjalan. Jika Anda ingin memeriksa semua header respons dan arti masing-masing dalam konteks, maka Accept-Encoding: deflate, gzip, br, zstd akan mengannotasikannya termasuk Penganalisis Header HTTP , dan direktif cache-control. Vary, Content-Encodinggzip vs Brotli vs Zstd

Tiga algoritma yang secara praktis relevan untuk HTTP saat ini. Angka-angka benchmark di bawah ini berasal dari

benchmark resmi Zstd pada kumpulan data Silesia — dataset standar dari berbagai file dunia nyata (HTML, kode sumber, PDF, database), diuji pada prosesor Core i7-9700K. Beban JSON murni atau teks biasa biasanya kompresi lebih baik. gzip

AlgoritmaTingkatRasioKompresDekompresi
1 (cepat)2.74x69 MB/s380 MB/s380 MB/s
1 (cepat)6 (default)2.97x29.9 MB/s360 MB/s
1 (cepat)9 (maksimal)3.10x18 MB/s360 MB/s
Brotli43.18x104 MB/s440 MB/s
Brotli11 (maksimal)3.74x0.4 MB/s440 MB/s
Zstd2.74x2.88x430 MB/s1,380 MB/s
Zstd3 (default)3.01x320 MB/s1,350 MB/s
Zstd19 (maksimal)3.40x17.5 MB/s1,380 MB/s

1 (cepat) adalah dasar. Level 6 adalah pilihan yang tepat untuk penggunaan langsung — menghabiskan 65% lebih CPU untuk berpindah dari level 6 ke level 9 memberi Anda sekitar 4% perbaikan rasio. Tidak layak untuk respons dinamis. File statis yang dikompresi sebelumnya adalah perhitungan yang berbeda.

Brotli benar-benar mengungguli gzip pada biaya CPU yang sebanding pada tingkat 4-6, dan mendekompresi sekitar 20% lebih cepat. Alasannya: Brotli memiliki kamus statis yang disesuaikan untuk konten web — entitas HTML, nama field HTTP, kata kunci JavaScript. Ini memberi rasio yang lebih baik dibandingkan kompresor umum pada bahan yang sama. Level 11 hanya layak untuk aset statis yang sudah dikompresi; pada kecepatan kompresi 0.4 MB/s, Anda akan mengkompresi sekitar 25MB per menit. Ini adalah langkah build, bukan proses permintaan.

Zstd adalah cerita kecepatan. Level default (3) memberikan rasio yang sama dengan gzip tetapi mengkomprimasi 10x lebih cepat dan mendekompresi hampir 4x lebih cepat. Keterbatasannya adalah dukungan browser: Chrome 118+ (Oktober 2023), Firefox 126+ (Mei 2024), Safari 18+ (akhir 2024). Belum cukup universal untuk digunakan sebagai satu-satunya algoritma, tetapi jika server Anda menegosiasikan dengan benar, menambahkan Zstd hanya membutuhkan beberapa baris konfigurasi dan membantu klien yang mengumumkan kehadirannya. Zstd pada level 19 mendekati rasio Brotli-11 tanpa hukuman kecepatan kompresi yang kritis, membuatnya lebih dapat digunakan untuk pekerjaan langsung pada kebutuhan kompresi tinggi.

Dukungan Browser dan Klien

AlgoritmakromFirefoxTaman SafariTepianBahasa pemrograman Node.js
1 (cepat)SemuaSemuaSemuaSemuaDibangun secara bawaan (zlib)
deflateSemuaSemuaSemuaSemuaDibangun secara bawaan (zlib)
Brotli (br)51+44+11+15+v10.16+
Zstd118+126+18+118+v21+

Satu keanehan penting: br dan zstd hanya muncul dalam Accept-Encoding koneksi HTTPS. Browser secara sengaja tidak mengumumkan mereka dalam koneksi HTTP biasa — ini adalah perlindungan terhadap serangan MITM yang dapat menyuntikkan header enkoding. Jika Anda menguji di http://localhost dan bertanya mengapa Anda hanya melihat gzip, deflate, itu sebabnya. Uji melalui HTTPS atau gunakan curl secara langsung (curl tidak menerapkan pembatasan ini).

Empat Konfigurasi yang Salah dan Menghancurkan Fungsinya Secara Sengaja

1. gzip_proxied hilang (nginx reverse proxy)

modul nginx gzip mengkomprimasi respons yang dihasilkan sendiri. Untuk permintaan yang di-proxy (aplikasi upstream ke nginx ke klien), Anda membutuhkan gzip_proxied — jika tidak, nginx hanya mengkomprimasi respons dari handler konten sendiri, bukan dari proxy_pass upstream.

# This is NOT enough when nginx is a reverse proxy:
gzip on;
gzip_types text/plain application/json application/javascript text/css;

# You need this too:
gzip_proxied any;

Sebagian besar pengaturan nginx adalah reverse proxy. Sebagian besar tutorial mengabaikan gzip_proxied. Dua fakta ini menjelaskan banyak respons yang tidak dikompresi secara diam-diam.

2. Tipe MIME tidak ada dalam gzip_types

default nginx gzip_types adalah text/html hanya. JSON, CSS, JavaScript, SVG — semua tidak dikompresi kecuali secara eksplisit daftar:

gzip_types
  text/plain
  text/css
  text/xml
  text/javascript
  application/json
  application/javascript
  application/xml
  application/rss+xml
  image/svg+xml;

nginx membandingkan berdasarkan tipe MIME dasar, jadi application/json tetapi tidak application/json; charset=utf-8. Tidak perlu mengatur variasi charset secara terpisah.

3. Proxy tengah menghilangkan Accept-Encoding

AWS ALB, worker Cloudflare yang salah dikonfigurasi, dan beberapa pengaturan API gateway menghilangkan atau mengubah Accept-Encoding sebelum mencapai asal. Server tidak pernah melihat header tersebut, beralih ke tidak ada kompresi, dan semua yang ada di bawahnya berpikir fitur ini rusak ketika masalah sebenarnya adalah middleware. Tidak muncul kesalahan di mana pun dalam rantai.

Debug dengan membandingkan respons asal dengan respons CDN:

# Via CDN/proxy
curl -sI -H "Accept-Encoding: gzip, br" https://example.com/api/data

# Direct to origin (bypassing CDN via --resolve or direct IP)
curl -sI -H "Accept-Encoding: gzip, br" --resolve "example.com:443:ORIGIN_IP" https://example.com/api/data

Jika asal mengembalikan Content-Encoding: gzip langsung tetapi respons CDN tidak memiliki Content-Encoding, maka CDN menghilangkan sesuatu — lebih mungkin menghilangkan Accept-Encoding yang masuk sehingga asal tidak mengkomprimasi pada awalnya.

4. Aplikasi upstream mengkomprimasi, lalu nginx mencoba mengkomprimasi lagi

Jika aplikasi Anda (Node.js/Go/Python) mengkomprimasi isi respons dan mengatur Content-Encoding: gzip, nginx seharusnya melewati kompresi ganda — tetapi ini tergantung pada waktu header. Jika aplikasi mengirimkan header di tengah aliran atau deteksi nginx bersaing, Anda bisa menghasilkan limbah yang dikompresi dua kali yang tidak dapat didekompresi oleh klien.

Solusi bersih: biarkan nginx mengendalikan semua kompresi. Hapus middleware kompresi dari aplikasi Anda (modul express’s compression , Go’s gzip.Handler, dll.), kembalikan respons murni, dan biarkan nginx mengkomprimasi di tepi. Dapatkan kinerja yang sama, tanpa risiko kompresi ganda.

Konfigurasi yang Berfungsi

nginx

gzip on;
gzip_vary on;         # adds Vary: Accept-Encoding automatically
gzip_proxied any;     # compress responses from proxied upstreams
gzip_comp_level 6;
gzip_min_length 256;  # skip tiny responses where overhead isn't worth it
gzip_types
  text/plain
  text/css
  text/xml
  text/javascript
  application/json
  application/javascript
  application/xml
  application/rss+xml
  image/svg+xml;

# Brotli requires the ngx_brotli module
# https://github.com/google/ngx_brotli
brotli on;
brotli_comp_level 4;
brotli_static on;     # serve pre-compressed .br files when they exist
brotli_types
  text/plain
  text/css
  application/json
  application/javascript
  image/svg+xml;

Apache

LoadModule deflate_module modules/mod_deflate.so
AddOutputFilterByType DEFLATE text/html text/plain text/css   application/json application/javascript image/svg+xml
Header append Vary Accept-Encoding

# mod_brotli requires Apache 2.4.26+
LoadModule brotli_module modules/mod_brotli.so
AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/css   application/json application/javascript image/svg+xml

Caddy

Caddy mengaktifkan gzip dan Brotli secara default. Untuk menambahkan Zstd secara eksplisit:

example.com {
  encode gzip zstd br
  reverse_proxy localhost:3000
}

Tidak ada daftar tipe MIME, tidak ada gzip_proxied kasus khusus, penanganan yang benar secara bawaan. Jawaban yang jujur terhadap pertanyaan "manakah server yang memiliki area terkecil untuk kesalahan konfigurasi terkait kompresi" adalah Caddy. Vary Pengujian Kompresi pada Payload Anda Sendiri

Angka-angka benchmark pada kumpulan data Silesia memberi tahu Anda kinerja relatif, tetapi payload Anda sendiri lebih penting. Respons API berulang dengan nama field yang konsisten mengkomprimasi secara berbeda dibandingkan JavaScript yang diminifikasi atau HTML yang campuran. Alat-alat ini memungkinkan Anda menguji payload tertentu secara langsung di browser tanpa memutar server kompresi lokal:

— tempel payload Anda, lihat ukuran yang dikompresi dan rasio secara langsung

Jika respons tidak dikompresi dan

Kesimpulan

mengonfirmasi tidak ada curl -sI , solusi hampir pasti merupakan salah satu dari empat konfigurasi di atas — paling mungkin Content-Encodinguntuk nginx, atau CDN yang mengonsumsi gzip_proxied any; header. Periksa asal secara langsung sebelum menyalahkan konfigurasi server Anda. Accept-Encoding Untuk pilihan algoritma: gzip-6 cukup untuk respons API dinamis dan membawa risiko konfigurasi yang sangat kecil. Tambahkan Brotli untuk aset statis — kompresi secara pra-kompressi pada level 11 selama langkah build, berikan dengan

, dan biarkan nginx jatuh kembali ke gzip untuk klien yang tidak mengumumkan brotli_static on. Zstd layak ditambahkan sekarang; biaya konfigurasi sangat kecil dan jejak browser-nya berkembang cepat. Menawarkan ketiga algoritma dengan penanganan yang benar bradalah posisi yang tepat untuk apa pun yang baru. Vary: Accept-Encoding gzip, Brotli, Zstd: Kompresi HTTP untuk Pengembang yang Menetapkan content-encoding: identity secara Kesalahan 2

Ingin bebas iklan? Bebas Iklan Hari Ini

Instal Ekstensi Kami

Tambahkan alat IO ke browser favorit Anda untuk akses instan dan pencarian lebih cepat

Ke Ekstensi Chrome Ke Ekstensi Tepi Ke Ekstensi Firefox Ke Ekstensi Opera

Papan Skor Telah Tiba!

Papan Skor adalah cara yang menyenangkan untuk melacak permainan Anda, semua data disimpan di browser Anda. Lebih banyak fitur akan segera hadir!

IKLAN · HAPUS?
IKLAN · HAPUS?
IKLAN · HAPUS?

Pojok Berita dengan Sorotan Teknologi

Terlibat

Bantu kami untuk terus menyediakan alat gratis yang berharga

Belikan aku kopi
IKLAN · HAPUS?