gzip, Brotli, Zstd Pengompresan HTTP untuk Pengembang yang Menetapkan content-encoding: identity secara Accidental
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.
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
| Algoritma | Tingkat | Rasio | Kompres | Dekompresi |
|---|---|---|---|---|
| 1 (cepat) | 2.74x | 69 MB/s | 380 MB/s | 380 MB/s |
| 1 (cepat) | 6 (default) | 2.97x | 29.9 MB/s | 360 MB/s |
| 1 (cepat) | 9 (maksimal) | 3.10x | 18 MB/s | 360 MB/s |
| Brotli | 4 | 3.18x | 104 MB/s | 440 MB/s |
| Brotli | 11 (maksimal) | 3.74x | 0.4 MB/s | 440 MB/s |
| Zstd | 2.74x | 2.88x | 430 MB/s | 1,380 MB/s |
| Zstd | 3 (default) | 3.01x | 320 MB/s | 1,350 MB/s |
| Zstd | 19 (maksimal) | 3.40x | 17.5 MB/s | 1,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
| Algoritma | krom | Firefox | Taman Safari | Tepian | Bahasa pemrograman Node.js |
|---|---|---|---|---|---|
| 1 (cepat) | Semua | Semua | Semua | Semua | Dibangun secara bawaan (zlib) |
| deflate | Semua | Semua | Semua | Semua | Dibangun secara bawaan (zlib) |
| Brotli (br) | 51+ | 44+ | 11+ | 15+ | v10.16+ |
| Zstd | 118+ | 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
- Penguji Gzip / Zlib / Deflate — uji kompresi Brotli pada berbagai tingkat kualitas
- Encoder/Decoder Kompresi Brotli — enkripsi dan dekripsi Zstd di browser
- Alat Kompresi Zstandard (Zstd) Penting saat memutuskan apakah harus mempre-kompresi aset statis pada Brotli-11 atau hanya biarkan nginx mengelola gzip secara langsung. Tempel payload respons Anda, bandingkan rasio, dan buat keputusan dengan angka nyata.
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
Instal Ekstensi Kami
Tambahkan alat IO ke browser favorit Anda untuk akses instan dan pencarian lebih cepat
恵 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!
Alat Wajib Coba
Lihat semua Pendatang baru
Lihat semuaMemperbarui: Kita alat terbaru ditambahkan pada 16 Juni 2026
