Keine Werbung mögen? Gehen Werbefrei Heute

gzip, Brotli, Zstd HTTP-Verschließung für Entwickler, die content-encoding: identity versehentlich festlegen

Aktualisiert am

Wie die HTTP-Kompression-Verhandlung funktioniert (Accept-Encoding / Content-Encoding), eine Seitenanzeige von gzip, Brotli und Zstd, wie die Kompression mit curl überprüft werden kann, und vier fehlerhafte Konfigurationen, die sie schweigend deaktivieren.

gzip, Brotli, Zstd: HTTP-Kompression für Entwickler, die content-encoding: identity versehen haben, durch Zufall 1
ANZEIGE Entfernen?

Ihre nginx-Konfiguration enthält gzip on;. Ihre Anwendung gibt JSON zurück. Der Antworttext ist immer noch 35 KB unkomprimiert. Keine Fehler, keine Warnungen – die Kompression erfolgt einfach schweigend nicht.

Das ist normalerweise eine der vier falschen Konfigurationen. Aber zuerst: Wie die Verhandlung tatsächlich funktioniert.

Wie HTTP-Kompression-Verhandlung funktioniert

Zwei Header, nichts sonst. Der Client benachrichtigt, was er dekomprimieren kann in Accept-Encoding. Der Server wählt ein Algorithmus, komprimiert den Körper und erklärt seine Wahl in 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

Der Vary: Accept-Encoding Header ist nicht optional, wenn Sie die Richtigkeit des CDN-Caching beachten. Ohne ihn könnte ein CDN eine Brotli-komprimierte Antwort speichern und an einen Client liefern, der nur Brotli angekündigt hat gzip In Accept-Encoding. Dieser Client versucht dann, Brotli als gzip zu dekomprimieren und erhält Abfall. nginx’s gzip_vary on; fügt dies automatisch hinzu.

Content-Encoding: identity ist technisch gültig – es bedeutet „keine Kompression“ – aber niemand setzt es explizit. Der tatsächliche Fehlermodus ist der Gegenteil: kein Content-Encoding Header überhaupt, wenn Sie einen erwartet.

Kompression wird tatsächlich funktionieren überprüft

Bevor Sie die Konfiguration debuggen, bestätigen Sie das Problem:

# 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 sendet Accept-Encoding: deflate, gzip, br, zstd automatisch und dekomprimiert die Antwort. Wenn beide Zahlen übereinstimmen, wird die Kompression nicht aktiviert. Wenn Sie alle Antwortheader überprüfen und das Bedeutung jedes Headers im Kontext sehen möchten, dann HTTP Header Analyzer wird sie diese annotieren einschließlich Vary, Content-Encodingund Cache-Control-Anweisungen.

gzip vs Brotli vs Zstd

Drei Algorithmen sind heute praktisch relevant für HTTP. Die Benchmark-Zahlen unten stammen aus den offiziellen Benchmark-Tests von Zstd auf dem Silesia-Korpus – einem Standarddatensatz aus gemischten realen Dateien (HTML, Quellcode, PDFs, Datenbanken), getestet auf einem Core i7-9700K. Pure JSON oder einfacher Textinhalt komprimiert sich typischerweise besser.

AlgorithmusEbeneVerhältnisKompresseDekomprimieren
gzip1 (schnell)2.74x69 MB/s380 MB/s
gzip6 (Standard)2.97x29.9 MB/s360 MB/s
gzip9 (Maximal)3.10x18 MB/s360 MB/s
Brotli43.18x104 MB/s440 MB/s
Brotli11 (Maximal)3.74x0.4 MB/s440 MB/s
Zstd1 (schnell)2.88x430 MB/s1,380 MB/s
Zstd3 (Standard)3.01x320 MB/s1,350 MB/s
Zstd19 (Maximal)3.40x17.5 MB/s1,380 MB/s

gzip ist die Grundlage. Ebene 6 ist die richtige Wahl für die Echtzeit-Verarbeitung – der zusätzliche CPU-Aufwand von 65% bei der Übergang von Ebene 6 zu Ebene 9 gewinnt etwa 4% bessere Leistung. Das ist für dynamische Antworten nicht wert. Vorgeschaltete statische Dateien sind eine andere Berechnung.

Brotli leistet tatsächlich bei vergleichbaren CPU-Kosten bei Ebenen 4–6 besser als gzip und dekomprimiert etwa 20% schneller. Der Grund: Brotli verfügt über einen statischen Wörterbuch, das für Webinhalte optimiert ist – HTML-Entitäten, HTTP-Feldnamen, JavaScript-Schlüsselwörter. Es erreicht bessere Kompressionsverhältnisse als ein allgemeiner Kompressor auf dem gleichen Material. Ebene 11 ist nur für vorgeschaltete statische Assets geeignet; bei einer Kompressionsgeschwindigkeit von 0,4 MB/s würden Sie etwa 25 MB pro Minute komprimieren. Das ist ein Build-Schritt, nicht ein Request-Handler.

Zstd ist die Geschwindigkeitsgeschichte. Die Standardstufe (3) hat das gleiche Verhältnis wie gzip, komprimiert jedoch 10-mal schneller und dekomprimiert fast 4-mal schneller. Die Hauptbeschränkung ist die Browserunterstützung: Chrome 118+ (Oktober 2023), Firefox 126+ (Mai 2024), Safari 18+ (Spät 2024). Es ist noch nicht universell genug, um als einzige Algorithmen zu verwenden, aber wenn Ihr Server richtig verhandelt, kostet die Hinzufügung von Zstd nur einige Konfigurationszeilen und hilft Clients, die es angekündigt haben. Zstd auf Ebene 19 nähert sich Brotli-11 in Verhältnis an, ohne die katastrophale Kompressionsgeschwindigkeitspenale, was es für hochbelastete Echtzeit-Arbeiten nutzbarer macht.

Browser- und Client-Unterstützung

AlgorithmusChromeFirefoxSafariEdgeNode.js
gzipAlleAlleAlleAlleeingebaut (zlib)
deflateAlleAlleAlleAlleeingebaut (zlib)
Brotli (br)51+44+11+15+v10.16+
Zstd118+126+18+118+v21+

Ein wichtiger Besonderheit: br und zstd erscheinen nur in Accept-Encoding über HTTPS-Verbindungen. Browser erklären absichtlich nicht, dass sie sie über HTTP-Verbindungen angekündigt haben – es ist eine Verteidigung gegen MITM-Angriffe, die Encoding-Header injizieren könnten. Wenn Sie auf http://localhost testen und sich fragen, warum Sie nur sehen gzip, deflate, das ist der Grund. Testen Sie über HTTPS oder verwenden Sie curl direkt (curl erfüllt diese Beschränkung nicht).

Vier falsche Konfigurationen, die es schweigend brechen

1. gzip_proxied ist fehlend (nginx Reverse Proxy)

nginx’s gzip Modul komprimiert die Antworten, die es selbst generiert. Für vermittelte Anfragen (upstream App zu nginx zu Client) benötigen Sie gzip_proxied – ansonsten komprimiert nginx nur Antworten von seinen eigenen Content-Handlers, nicht von proxy_pass Upstreams.

# 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;

Die meisten nginx-Einstellungen sind Reverse-Proxy. Die meisten Tutorials verpassen gzip_proxied. Diese beiden Tatsachen erklären viele schweigend unkomprimierte Antworten.

2. MIME-Typ ist nicht in gzip_types enthalten

nginx’s Standard gzip_types Ist text/html nur. JSON, CSS, JavaScript, SVG – alle unkomprimiert, es sei denn, sie werden explizit aufgelistet:

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

nginx vergleicht auf dem Basis-MIME-Typ, also application/json abdeckt application/json; charset=utf-8. Es ist nicht notwendig, die Zeichensatzvarianten separat aufzulisten.

3. Ein mittlerer Proxy entfernt Accept-Encoding

AWS ALB, falsch konfigurierte Cloudflare-Worker und einige API-Gateway-Einstellungen entfernen oder ändern Accept-Encoding bevor es an Ihren Ursprung kommt. Der Server sieht den Header nicht, fällt auf keine Kompression zurück und alle untergeordneten Systeme denken, das Feature sei defekt, während das echte Problem im Middleware liegt. Kein Fehler erscheint irgendwo in der Kette.

Debuggen Sie durch Vergleich von Ursprungantwort und CDN-Antwort:

# 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

Wenn der Ursprung direkt Content-Encoding: gzip zurückgibt, aber die CDN-Antwort kein Content-Encodinghat, entfernt der CDN etwas – wahrscheinlich entfernt Accept-Encoding inbegriffen, sodass der Ursprung nie komprimiert.

4. Die upstream-Anwendung komprimiert, dann versucht nginx erneut zu komprimieren

Wenn Ihre Node.js/Go/Python-Anwendung den Antworttext komprimiert und Content-Encoding: gzipsetzt, sollte nginx die Doppelkompression vermeiden – aber dies hängt von Header-Timing ab. Wenn der upstream den Header während der Datenübertragung sendet oder nginx’s Erkennung konkurriert, können Sie mit doppelt komprimierten Daten enden, die die Clients nicht entschlüsseln können.

Die klare Lösung: Lassen Sie nginx alle Kompression übernehmen. Entfernen Sie die Kompressions-Middleware aus Ihrer Anwendung (express’s compression Modul, Go’s gzip.Handler, usw.), geben Sie einfache Antworten zurück und lassen Sie nginx die Kompression am Rand durchführen. Gleiches Leistungsvermögen, kein Risiko für Doppelkompression.

Funktionierende Konfigurationen

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 aktiviert standardmäßig gzip und Brotli. Um Zstd explizit hinzuzufügen:

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

Keine MIME-Typ-Listen, keine gzip_proxied Ausnahmefälle, korrekte Vary Behandlung aus der Box. Die ehrliche Antwort auf „welche Server hat die geringste Kompressionsfehlerfläche“ ist Caddy.

Kompression auf eigenen Payloads testen

Benchmark-Zahlen auf dem Silesia-Korpus sagen Ihnen nur das relative Leistungsverhältnis, aber Ihr spezifischer Payload zählt mehr. Eine wiederholende JSON-API-Antwort mit konstanten Feldern komprimiert sich anders als minimierte JavaScript oder gemischte HTML. Diese Tools ermöglichen es Ihnen, spezifische Payloads im Browser zu testen, ohne eine lokale Kompressions-Server aufzubauen:

Nützlich, wenn Sie entscheiden, ob Sie statische Assets bei Brotli-11 vorgeschaltet oder einfach gzip auf der Stelle lassen. Fügen Sie Ihre tatsächliche Antwort-Payload ein, vergleichen Sie die Verhältnisse und treffen Sie die Entscheidung mit echten Zahlen.

Zusammenfassung

Wenn Antworten nicht komprimiert sind und curl -sI bestätigt, dass kein Content-Encodingist, ist die Lösung fast sicher eine der vier falschen Konfigurationen oben – wahrscheinlich gzip_proxied any; für nginx oder ein CDN, das Ihr Accept-Encoding Header verschlingt. Prüfen Sie direkt den Ursprung, bevor Sie Ihre Serverkonfiguration beschuldigen.

Für die Algorithmuswahl: gzip-6 ist für dynamische API-Antworten in Ordnung und hat praktisch kein Konfigurationsrisiko. Fügen Sie Brotli für statische Assets hinzu – komprimieren Sie sie bei Ebene 11 während des Builds, dient sie mit brotli_static onund lassen Sie nginx auf Clients zurückfallen, die nicht brangekündigt haben. Zstd lohnt sich jetzt hinzuzufügen; die Konfigurationskosten sind trivial und sein Browser-Fußabdruck wächst schnell. Die Bereitstellung aller drei Algorithmen mit korrekter Vary: Accept-Encoding Behandlung ist die richtige Haltung für alles Neue.

Möchten Sie werbefrei genießen? Werde noch heute werbefrei

Erweiterungen installieren

IO-Tools zu Ihrem Lieblingsbrowser hinzufügen für sofortigen Zugriff und schnellere Suche

Zu Chrome-Erweiterung Zu Kantenerweiterung Zu Firefox-Erweiterung Zu Opera-Erweiterung

Die Anzeigetafel ist eingetroffen!

Anzeigetafel ist eine unterhaltsame Möglichkeit, Ihre Spiele zu verfolgen. Alle Daten werden in Ihrem Browser gespeichert. Weitere Funktionen folgen in Kürze!

ANZEIGE Entfernen?
ANZEIGE Entfernen?
ANZEIGE Entfernen?

Nachrichtenecke mit technischen Highlights

Beteiligen Sie sich

Helfen Sie uns, weiterhin wertvolle kostenlose Tools bereitzustellen

Kauf mir einen Kaffee
ANZEIGE Entfernen?