Опирается на правила: R-HDR-1..4 и R-HDR-X1 из REST API Style Guide → раздел Заголовки и трассировка.

Важно знать

  • Стандартные HTTP-заголовки — по назначению (Content-Type, Authorization, Location, ETag).
  • Кастомные заголовки — с доменным префиксом единым для всех сервисов проекта.
  • Idempotency-Key для POST-запросов, безопасных при повторной отправке.
  • traceparent (W3C Trace Context) — для distributed tracing.
  • trace-id из traceparent используется как traceId в теле ошибки RFC 9457.
  • Префикс X- в кастомных заголовках — устарел по RFC 6648.

Заголовки несут метаданные о запросе/ответе. Большинство уже стандартизировано HTTP (Content-Type, Accept, Authorization). UCP формулирует две дополнительные конвенции: Idempotency-Key для безопасности retry и traceparent для distributed observability.

Стандартные заголовки

R-HDR-1: используются по назначению.

HeaderНазначениеПример
Content-Typeтип тела запроса/ответаapplication/json
Acceptожидаемый тип ответаapplication/json
AuthorizationаутентификацияBearer eyJhbGci...
LocationURL созданного ресурса при 201 Created/api/v1/orders/550e...
ETagверсия ресурса для кеширования"33a64df5"
If-None-Matchусловный GET"33a64df5"
If-Matchoptimistic concurrency для PUT/PATCH"33a64df5"
Cache-Controlкеширование responseno-cache, max-age=300
GET /api/v1/orders/550e8400-...
Accept: application/json
Authorization: Bearer eyJhbGci...
If-None-Match: "33a64df5"

HTTP/1.1 200 OK
Content-Type: application/json
ETag: "33a64df5"
Cache-Control: private, max-age=60

Кастомные заголовки с доменным префиксом

R-HDR-2: единый префикс для всех сервисов компании.

Shop-Request-Id: 550e8400-e29b-41d4-a716-446655440000
Shop-Client-Version: 2.1.0
Shop-Tenant-Id: acme
  • Shop- — выбранный префикс (пример, в реальном проекте — свой).
  • Един для всех сервисов — order-service, payment-service, billing-service — все используют Shop-*.
  • Фиксируется в стандартах команды один раз, не варьируется.

Shop-Request-Idtraceparent:

  • Shop-Request-Id — идентификатор конкретного запроса от клиента (для дедупликации, логирования).
  • traceparent — идентификатор всей цепочки вызовов (distributed trace).

Idempotency-Key

R-HDR-3: безопасный retry.

POST /api/v1/orders
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json

{ "items": [...] }

Контракт:

  • Клиент один раз генерирует ключ на бизнес-операцию.
  • Повторный POST с тем же ключом → backend возвращает первый результат, не создаёт дубль.
  • Другой payload с тем же ключом → 409 Conflict.

Для money — обязателен (AUTH-19). См. Auth → idempotency.

@PostMapping("/orders")
public ResponseEntity<OrderResponse> create(
    @RequestHeader("Idempotency-Key") String key,
    @RequestBody @Valid CreateOrderRequest request
) { ... }

Реализация — Distributed → idempotency (idempotency_record таблица).

traceparent — W3C Trace Context

R-HDR-4: distributed tracing.

Стандарт: W3C Trace Context.

traceparent: {version}-{trace-id}-{parent-id}-{trace-flags}

00-1f2a8b6c7d3e4f5a9b0c1d2e3f4a5b6c-7a8b9c0d1e2f3a4b-01
│  │                                │                │
│  trace-id (32 hex)                 parent-id (16)  flags
version
  • version — формат, сейчас всегда 00.
  • trace-id — 32 hex, уникальный ID всей цепочки вызовов.
  • parent-id — 16 hex, ID текущего span.
  • trace-flags — 2 hex, например 01 = sampled.

Правила обработки

Client → Service A → Service B → Service C
                   ↓
                   Service B продолжает trace
  1. Клиент прислал traceparent → сервис использует его trace-id, создаёт новый parent-id для своего span.
  2. Клиент не прислал → сервис генерирует traceparent на входе.
  3. trace-id из traceparent используется как traceId в теле ошибки RFC 9457 (см. Ошибки).

В Spring OpenTelemetry — автоматически:

  • opentelemetry-spring-boot-starter извлекает traceparent.
  • Прокидывает в outgoing HTTP / Kafka headers.
  • traceId/spanId в MDC для логов.

Подробнее — Observability → tracing.

tracestate

Опциональный, для vendor-специфичных данных:

traceparent: 00-1f2a8b6c...-7a8b9c0d...-01
tracestate: vendor1=value1,vendor2=value2

Большинству приложений не нужен — Spring OpenTelemetry заполняет если используется vendor-specific tracer.

Запреты

X- префикс — устарел

R-HDR-X1: запрещено.

X-Request-Id: ...              ✗ — устарело по RFC 6648
Shop-Request-Id: ...           ✓ — доменный префикс

RFC 6648 (June 2012) официально deprecated X- префикс для кастомных заголовков. Альтернативы:

  • Доменный префикс компании (Shop-, Bank-).
  • Стандартизованные headers (если применимо — Authorization, Content-Type).

Исключения (исторические, всё ещё используются):

  • X-Forwarded-For — стандарт de facto для proxy chain.
  • X-Request-Id — широко используется, но в новых проектах лучше Shop-Request-Id.

Что запрещено

АнтипаттернПравилоЧто взамен
X-Custom-Header префиксR-HDR-X1доменный префикс компании
Кастомный header без префиксаR-HDR-2Shop-* consistent
Authorization без Bearer для JWTR-HDR-1Bearer eyJhbGci...
Idempotency-Key для GETR-HDR-3только POST/PATCH
Самописный Tracking-Id вместо traceparentR-HDR-4W3C standard
trace-id 16 hex (не 32)R-HDR-432 hex
Header в body вместо HTTP headerR-HDR-1в HTTP headers
X-Forwarded-For для tenant-routingR-HDR-2Shop-Tenant-Id

Куда дальше

  • REST API → Заголовки (нормативно) — формулировки.
  • Auth → idempotency — Idempotency-Key для money.
  • Distributed → idempotency — реализация на backend.
  • Observability → tracing — OpenTelemetry, traceparent propagation.
  • Observability → context propagation — MDC traceId.
  • Ошибки RFC 9457 — traceId в теле ошибки.
  • JSON и формат ответов — Location для 201.