HTTP ETag Header

Typ

Der ETag-Header ist ein HTTP-Response-Header, mit dem der Server einen eindeutigen Identifier für eine spezifische Version einer Ressource bereitstellt.

Syntax

Der Header enthält einen String-Wert, der als Versions-Identifier dient.

http
ETag: "v123-abc456"
ETag: W/"xyz789-weak"

Direktiven

Der ETag-Header verwendet folgende Syntax-Elemente:

strong-validator
Ein Strong-ETag ohne W/-Prefix garantiert byte-für-byte-Identität. Format: "value". Verwendet für exakte Validierung und Range-Requests.
weak-validator
Ein Weak-ETag mit W/-Prefix garantiert semantische, aber nicht byte-genaue Identität. Format: W/"value". Verwendet für komprimierte oder dynamisch generierte Inhalte.
opaque-value
Der ETag-Wert ist ein opaker String. Clients dürfen keine Annahmen über dessen Struktur machen. Server können Hash, Version oder Timestamp verwenden.

Beispiele

Conditional-GET mit ETag für API-Caching

Ein Client fragt eine API-Ressource zum ersten Mal an:

http
GET /api/v1/products/12345 HTTP/1.1
Host: api.example.com
Accept: application/json

Der Server antwortet mit ETag:

http
HTTP/1.1 200 OK
ETag: "v5-9a8b7c6d"
Cache-Control: private, must-revalidate
Content-Type: application/json

{
  "product_id": "12345",
  "name": "Premium Widget",
  "price": 99.99,
  "stock": 42
}

Client sendet Conditional-Request mit If-None-Match:

http
GET /api/v1/products/12345 HTTP/1.1
Host: api.example.com
If-None-Match: "v5-9a8b7c6d"
Accept: application/json

Server antwortet mit 304 wenn unverändert:

http
HTTP/1.1 304 Not Modified
ETag: "v5-9a8b7c6d"
Cache-Control: private, must-revalidate

Optimistic Concurrency Control mit ETag

Ein Client liest eine Ressource und erhält ETag:

http
GET /api/v1/orders/ORD-789 HTTP/1.1
Host: api.example.com
http
HTTP/1.1 200 OK
ETag: "v1-abc123"
Content-Type: application/json

{
  "order_id": "ORD-789",
  "status": "pending",
  "total": 199.99
}

Client aktualisiert mit If-Match zur Konflikt-Vermeidung:

http
PUT /api/v1/orders/ORD-789 HTTP/1.1
Host: api.example.com
If-Match: "v1-abc123"
Content-Type: application/json

{
  "status": "confirmed",
  "total": 199.99
}

Server akzeptiert Update wenn ETag übereinstimmt:

http
HTTP/1.1 200 OK
ETag: "v2-def456"
Content-Type: application/json

{
  "order_id": "ORD-789",
  "status": "confirmed",
  "total": 199.99
}

Wenn zwischenzeitlich geändert, lehnt Server ab:

http
HTTP/1.1 412 Precondition Failed
ETag: "v2-xyz999"
Content-Type: application/json

{
  "error": "conflict",
  "message": "Resource was modified by another client"
}

Weak-ETag für komprimierte API-Responses

Eine API verwendet Weak-ETags für komprimierte Inhalte:

http
GET /api/v1/reports/monthly HTTP/1.1
Host: api.example.com
Accept-Encoding: gzip
http
HTTP/1.1 200 OK
ETag: W/"report-2025-10-gzip"
Content-Encoding: gzip
Vary: Accept-Encoding
Content-Type: application/json

[Komprimierte JSON-Daten]

ETag-Validation-and-Concurrency-Flow

Der Ablauf der ETag-basierten Validierung und Concurrency Control in REST APIs.

plantuml
@startuml
actor "Client A" as ClientA
actor "Client B" as ClientB
participant "API Server" as API
database "Data Store" as Store

ClientA -> API: GET /api/v1/resource/1
API -> Store: Fetch resource
Store --> API: Data (version 1)
API --> ClientA: 200 OK\nETag: "v1"\n[data]

ClientB -> API: GET /api/v1/resource/1
API -> Store: Fetch resource
Store --> API: Data (version 1)
API --> ClientB: 200 OK\nETag: "v1"\n[data]

ClientA -> API: PUT /api/v1/resource/1\nIf-Match: "v1"\n[updated data]
API -> Store: Check ETag and update
Store --> API: Updated (version 2)
API --> ClientA: 200 OK\nETag: "v2"

ClientB -> API: PUT /api/v1/resource/1\nIf-Match: "v1"\n[different update]
API -> Store: Check ETag
Store --> API: ETag mismatch\n(now v2, not v1)
API --> ClientB: 412 Precondition Failed\nETag: "v2"\n[current data]

ClientB -> ClientB: Resolve conflict\nmerge changes

ClientB -> API: PUT /api/v1/resource/1\nIf-Match: "v2"\n[merged update]
API -> Store: Check ETag and update
Store --> API: Updated (version 3)
API --> ClientB: 200 OK\nETag: "v3"
@enduml

Vorteile für die Systemarchitektur

  • Reduziert Bandbreite durch 304-Responses bei unveränderter Ressource
  • Implementiert Optimistic Concurrency Control ohne komplexe Locking-Mechanismen
  • Verhindert Lost-Update-Problem bei konkurrierenden Schreibzugriffen
  • Ermöglicht effizientes CDN-Caching mit präziser Validierung
  • Unterstützt Range-Requests mit Strong-ETags für partielle Downloads

Spezifikation

Der ETag-Header ist in RFC 9110 Section 8.8.3 (HTTP Semantics) definiert.

Weitere Spezifikationen

If-None-Match Header, If-Match Header, Cache-Control Header