Сети и протоколы
HTTP-заголовки, кеширование и CORS
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 Ответ несёт ETag и Cache-Control: max-age=3600
- 2 Браузер кеширует ответ на 3600 секунд
- 3 Через 3600с кеш устаревает
- 4 Следующий запрос: браузер отправляет If-None-Match с сохранённым ETag
- 5 Сервер отвечает 304 Not Modified (пустое тело) если ETag совпадает
- 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?
Трассировка cross-origin API-вызова из браузерного приложения.
- 01Когда ставить Cache-Control: no-store против no-cache?
- 02Почему CORS не является защитным барьером для API?
- 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-позицию браузера на уровне заголовков.