HTTP-заголовки: основные

HTTP-заголовки (headers) — это пары ключ-значение, передаваемые в запросе и ответе HTTP, которые несут метаданные: тип контента, авторизацию, кеширование, CORS, сжатие и многое другое.

Зачем нужно

Без понимания заголовков невозможно правильно реализовать кеширование, CORS, аутентификацию через токены, content negotiation и безопасность. Заголовки — основной механизм передачи метаданных HTTP и управления поведением браузера и прокси.

Где используется

  • REST API — Content-Type, Authorization, Accept
  • Кеширование — Cache-Control, ETag, Last-Modified
  • CORS — Access-Control-Allow-Origin, Access-Control-Allow-Methods
  • Безопасность — Strict-Transport-Security, Content-Security-Policy

Основной контент

Заголовки запроса (Request Headers)

Accept: application/json          # клиент хочет получить JSON
Accept-Encoding: gzip, br         # поддерживает сжатие
Accept-Language: ru-RU,ru;q=0.9   # предпочитаемый язык
Authorization: Bearer eyJhbGc... # JWT токен или Basic auth
Content-Type: application/json    # тип тела запроса
Content-Length: 48                # размер тела в байтах
Host: api.example.com             # хост (обязательный в HTTP/1.1)
User-Agent: Mozilla/5.0...        # информация о клиенте
Cookie: sessionId=abc123          # куки
Referer: https://example.com/page # откуда пришёл запрос
X-Request-ID: uuid-v4             # уникальный ID запроса (custom)
If-None-Match: "abc123"           # условный запрос с ETag
If-Modified-Since: Thu, 01 Jan... # условный запрос по дате

Заголовки ответа (Response Headers)

Content-Type: application/json; charset=utf-8   # тип и кодировка ответа
Content-Length: 1024                             # размер ответа
Content-Encoding: gzip                           # ответ сжат
Cache-Control: max-age=3600, public              # правила кеширования
ETag: "abc123"                                   # версия ресурса
Last-Modified: Wed, 10 Apr 2026 12:00:00 GMT     # дата изменения
Location: /api/users/42                          # для 201 и 3xx редиректов
Set-Cookie: sessionId=abc; HttpOnly; Secure      # установить куки
WWW-Authenticate: Bearer realm="API"             # требование аутентификации
Access-Control-Allow-Origin: https://myapp.com  # CORS
X-RateLimit-Limit: 100                          # rate limit info
X-RateLimit-Remaining: 95
Retry-After: 60                                  # после 429 — когда повторить

Работа с заголовками в Node.js/Express

// Чтение заголовков запроса
app.get('/api', (req, res) => {
  const auth = req.get('Authorization');           // 'Bearer token...'
  const contentType = req.get('Content-Type');
  const allHeaders = req.headers;                  // объект со всеми

  // Установка заголовков ответа
  res.set('X-Custom-Header', 'value');
  res.setHeader('Cache-Control', 'no-cache');

  // Несколько заголовков
  res.set({
    'X-Request-ID': '123',
    'X-Processing-Time': '15ms'
  });

  res.json({ ok: true });
});

Cache-Control детально

Cache-Control: no-store              # не кешировать вообще (API с данными)
Cache-Control: no-cache              # кешировать, но проверять с сервером
Cache-Control: max-age=3600          # кешировать 1 час
Cache-Control: max-age=31536000, immutable  # кешировать год (хешированные файлы)
Cache-Control: private, max-age=600  # только браузер, не CDN/прокси
Cache-Control: public, max-age=3600  # можно кешировать в CDN

CORS заголовки

// При preflight запросе (OPTIONS)
res.set('Access-Control-Allow-Origin', 'https://myapp.com');
res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.set('Access-Control-Max-Age', '86400'); // кешировать preflight 24ч
res.set('Access-Control-Expose-Headers', 'X-Total-Count'); // заголовки видимые клиенту

Content Negotiation

app.get('/data', (req, res) => {
  const accept = req.get('Accept');

  if (accept?.includes('application/json')) {
    res.json({ data:  });
  } else if (accept?.includes('text/html')) {
    res.render('data');
  } else {
    res.status(406).json({ error: 'Not Acceptable' });
  }
});

Частые ошибки

  • Регистр заголовков — HTTP/1 заголовки регистронезависимы; HTTP/2 требует lowercase; req.headers в Node.js всегда lowercase
  • Кешировать API-ответыCache-Control: no-store обязателен для персональных данных и изменяемых ресурсов
  • Content-Type без charsetapplication/json — можно без, но text/html требует ; charset=utf-8
  • Не отправлять Content-Length — при стриминге и chunked transfer encoding не нужен; при буферизованном ответе Express устанавливает автоматически

Связанные темы

Ресурсы