PassFront
  1. PassFront
  2. База знаний
  3. HTTP и HTTPS

Как работает сжатие HTTP-ответов: gzip, brotli и Content-Encoding?

HTTP и HTTPS

Клиент в `Accept-Encoding` перечисляет поддерживаемые алгоритмы, сервер выбирает один, сжимает тело и указывает его в `Content-Encoding`; для текста это экономит 60–90% трафика.

Алгоритмы

  • gzip (DEFLATE) — поддерживается везде, быстрый, уровни 1–9.
  • brotli (br) — для текста обычно на 15–25% компактнее gzip благодаря встроенному словарю. Уровни 0–11: 11 очень медленный, поэтому статику сжимают заранее, а на лету берут 4–6. Браузеры объявляют br только по HTTPS.
  • zstd — быстрый, уже поддержан Chrome и Firefox.

Что сжимать

  • HTML, CSS, JS, JSON, SVG — да.
  • JPEG, PNG, WebP, видео, архивы — нет: они уже сжаты, получите лишний CPU и порой больше байт.
  • Ответы меньше ~1 КБ — выигрыш не окупает накладные расходы.
// сжать тело запроса (серверу нужен gunzip)
const json = new Blob([JSON.stringify(Array(1000).fill({ status: 'active' }))]);
const gz = await new Response(json.stream().pipeThrough(new CompressionStream('gzip'))).blob();
console.log(json.size, gz.size); // JSON сжимается в разы
await fetch('/api/items', { method: 'POST', body: gz, headers: { 'Content-Encoding': 'gzip' } });
for (const e of performance.getEntriesByType('resource')) // сжатие ответов
  if (e.encodedBodySize) console.log(e.name, (e.decodedBodySize / e.encodedBodySize).toFixed(1));

Подводные камни

  • Без Vary: Accept-Encoding CDN может отдать brotli клиенту, который его не понимает.
  • Content-Length — это размер сжатого тела.
  • BREACH: если в сжатом ответе секрет соседствует с данными атакующего, секрет угадывается по длине ответа даже через HTTPS.

Коротко для собеседования

Сервер сжимает только тем алгоритмом, который клиент объявил в Accept-Encoding: текст — brotli или gzip, уже сжатые картинки и видео не трогают. Лучше делать это на прокси или CDN, статику класть заранее сжатой и не забывать Vary: Accept-Encoding.

Другие вопросы раздела