awesome-everything EN
↑ Обратно к восхождению

Сети и протоколы

HTTP-заголовки, кеширование и CORS

Суть Слой заголовков HTTP — методы, статус-коды, Cache-Control, ETag, куки, CORS — где живут большинство операционных багов и происходят победы или поражения в безопасности.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на middle-высоте — в небе
◷ 16 min

HTTP-версия определяет как идут байты. Заголовки определяют что с ними происходит — кешируются ли они, кто может читать их cross-origin, как долго живут куки, и заставит ли браузер всегда использовать HTTPS. Ошибки в заголовках — самый частый источник production security-багов.

Методы и идемпотентность

HTTP определяет глаголы (методы): GET (чтение), POST (создание или обобщённый неидемпотентный), PUT (идемпотентная замена), DELETE (идемпотентное удаление), PATCH (частичное обновление), HEAD (GET только метаданных), OPTIONS (проверка возможностей), CONNECT (туннель для прокси).

Идемпотентность (RFC 9110 § 9.2.2): метод идемпотентен если многократный вызов даёт тот же результат что однократный. GET, HEAD, PUT, DELETE и OPTIONS безопасно повторять автоматически при таймауте. POST и PATCHнет — автоматический повтор может создать дублирующиеся заказы, платежи или записи.

Практическое следствие: HTTP-клиенты (браузеры, балансировщики, CDN) могут прозрачно повторять идемпотентные методы при сетевой ошибке. POST /orders никогда не должен повторяться без Idempotency-Key-заголовка или дедупликации на уровне приложения.

Статус-коды

Статус-коды по RFC 9110:

  • 1xx информационные: 100 Continue, 101 Switching Protocols (апгрейд WebSocket), 103 Early Hints.
  • 2xx успех: 200 OK, 201 Created (POST создал ресурс), 204 No Content (успешный DELETE), 206 Partial Content (range-запрос выполнен).
  • 3xx редирект: 301 Moved Permanently (браузеры кешируют навсегда), 302/307 Temporary Redirect, 304 Not Modified (cache validation hit — пустое тело).
  • 4xx ошибка клиента: 400, 401 Unauthorized (нужна аутентификация), 403 Forbidden (аутентифицирован но не разрешено), 404, 409 Conflict, 422, 429 Too Many Requests.
  • 5xx ошибка сервера: 500, 502 Bad Gateway, 503, 504 Gateway Timeout.

Частая ошибка: возвращать 200 OK с { "error": "not found" } в JSON-теле. CDN кешируют 200, retry-логика не срабатывает, консоль браузера не показывает ошибку. Используйте правильный статус-код.

Кеширование: Cache-Control и ETag

Браузер, CDN-edge и reverse proxies кешируют ответы. Cache-Control:

  • max-age=3600 — кешировать 3600 секунд; ревалидация не нужна до устаревания.
  • no-cache — хранить ответ, но ревалидировать с origin перед отдачей (отправляет If-None-Match). Для часто меняющихся данных.
  • no-storeне хранить вообще — ни в кеше браузера, ни на CDN. Для высокочувствительных данных (банковские выписки, страницы аккаунта).
  • private — только браузер может кешировать; CDN/прокси — нет. Для пользовательских данных.
  • public — любой кеш может хранить. CDN нужно это (или отсутствие Cache-Control) для кеширования.
  • stale-while-revalidate=60 — сразу отдать устаревшую копию, ревалидировать в фоне.

ETag позволяет условные запросы: сервер отправляет ETag: "v2" с ответом. При следующем запросе браузер включает If-None-Match: "v2". Если ETag совпадает — сервер отвечает 304 Not Modified с пустым телом — экономя трафик.

Расставь шаги по порядку

Расставьте cache-связанные события в типичном жизненном цикле:

  1. 1 Ответ несёт ETag и Cache-Control: max-age=3600
  2. 2 Браузер кеширует ответ на 3600 секунд
  3. 3 Через 3600с кеш устаревает
  4. 4 Следующий запрос: браузер отправляет If-None-Match с сохранённым ETag
  5. 5 Сервер отвечает 304 Not Modified (пустое тело) если ETag совпадает
  6. 6 Или 200 OK с новым телом + новым ETag если контент изменился

CORS — Cross-Origin Resource Sharing

Браузеры применяют same-origin policy: скрипт на a.example.com не может читать ответы с b.example.com по умолчанию. CORS открывает доступ:

  • Сервер отвечает Access-Control-Allow-Origin: https://a.example.com разрешая доступ с этого origin.
  • Wildcard * разрешает любой origin, но не может сочетаться с credentials — браузер отказывается отправлять куки или Authorization-заголовки к wildcard-origin.
  • Preflight-запросы (OPTIONS): для несimple методов (PUT, DELETE, кастомные заголовки), браузер сначала отправляет OPTIONS проверяя что сервер разрешает cross-origin доступ.
  • Access-Control-Allow-Credentials: true плюс явный не-wildcard origin позволяет cross-origin запросам нести куки и Auth-заголовки.

Ошибка в конфигурации CORS: Access-Control-Allow-Origin: * с Access-Control-Allow-Credentials: true — дыра в безопасности. Браузер предотвращает эту комбинацию, но некоторые прокси или фреймворки допускают её через баги, открывая атаки типа confused-deputy.

Куки: флаги безопасности

Сервер устанавливает куки через:

Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Strict; Max-Age=3600; Path=/
  • HttpOnly — блокирует JavaScript-доступ к куке (document.cookie не видит её). Основная XSS-защита для session токенов.
  • Secure — отправлять только по HTTPS. Без этого session-кука может уйти по HTTP.
  • SameSite=Strict — никогда не отправлять при cross-site запросах. SameSite=Lax — отправлять при безопасных cross-site навигациях (переход по ссылке) но не при POST cross-site. SameSite=None; Secure — отправлять при всех cross-site запросах (для легитимного третьесторонного контента).

Современные браузеры по умолчанию SameSite=Lax при отсутствии директивы — это намеренно ломает многие legacy third-party cookie flows.

Заголовки безопасности

  • Strict-Transport-Security (HSTS): браузеры всегда используют HTTPS для этого домена в течение max-age секунд.
  • Content-Security-Policy (CSP): определяет какие источники могут загружать скрипты, стили, фреймы. Мощная XSS-защита.
  • X-Content-Type-Options: nosniff — браузеры не угадывают MIME-тип из содержимого.
  • Referrer-Policy: strict-origin-when-cross-origin — ограничивает утечку URL в Referer-заголовке.

Контент-переговоры и range-запросы

Контент-переговоры: клиенты сообщают предпочтения через Accept-заголовки. Accept: application/json, text/html;q=0.9. Заголовок Vary сообщает кешам какие request-заголовки влияют на ответ — без Vary: Accept-Encoding кеш может отдать Brotli-сжатый ответ клиенту не поддерживающему Brotli.

Range-запросы: Range: bytes=500-999 запрашивает диапазон байт; сервер отвечает 206 Partial Content. Используется для HTTP-видеостриминга и resume-after-disconnect.

Викторина

Какой HTTP-метод требуется быть идемпотентным согласно RFC 9110?

Викторина

Что означает Cache-Control: no-store для браузера и CDN?

Проследи
1/4

Трассировка cross-origin API-вызова из браузерного приложения.

1
Step 1 of 4
JavaScript на https://app.example.com вызывает fetch('https://api.other.com/data') с credentials. Что браузер делает первым?
2
Locked
OPTIONS preflight приходит на сервер. Какие заголовки должен вернуть сервер для продолжения?
3
Locked
Preflight успешен. Браузер отправляет реальный GET. API возвращает данные с ACAO: https://app.example.com и ACAC: true. Может ли JavaScript прочитать ответ?
4
Locked
Разработчик меняет сервер на Access-Control-Allow-Origin: * для упрощения. Что ломается?
Вспомните перед уходом
  1. 01
    Когда ставить Cache-Control: no-store против no-cache?
  2. 02
    Почему CORS не является защитным барьером для API?
  3. 03
    Что делает SameSite=Lax и почему он стал дефолтом браузеров?
Итог

HTTP-методы определяют намеренную операцию — идемпотентные методы (GET, HEAD, PUT, DELETE) можно автоматически повторять; неидемпотентные (POST, PATCH) — нельзя без idempotency-ключей. Статус-коды — семантические сигналы на которые полагается HTTP-инфраструктура (CDN, retry-логика, browser UI). Cache-Control (max-age, no-cache, no-store, private) контролирует где и как долго хранятся ответы; ETag позволяет дешёвую ревалидацию через 304 Not Modified. CORS применяется браузером, не сервером — не механизм контроля доступа. Куки требуют HttpOnly (блокирует XSS), Secure (только HTTPS) и SameSite=Lax или Strict (CSRF-защита). HSTS и CSP укрепляют security-позицию браузера на уровне заголовков.

Связанные уроки
Продолжить восхождение ↑HTTP-стриминг, SSE, WebSocket и gRPC
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.