API-Änderungen

Der API-Sunset-Header, und wann man ihn sendet

5 Min. Lesezeit

Sunset ist ein einzelner Response-Header, definiert in RFC 8594, der einem Aufrufer sagt, wann eine Ressource aufhört zu antworten. API-Abkündigung behandelt den vollständigen Announce-Remind-Brownout-Retire-Zeitplan und die dazugehörigen Ankündigungen; hier geht es um das eine maschinenlesbare Signal in diesem Zeitplan, was es tatsächlich sagt, und den einen Fall, in dem die RFC selbst sagt, man solle ihn nicht senden.

Was sagt der Sunset-Header, und was sagt er nicht?

Er trägt ein einzelnes HTTP-Datum, den Zeitpunkt, an dem die Ressource voraussichtlich nicht mehr antwortet:

Sunset: Sat, 31 Dec 2028 23:59:59 GMT

Die RFC nennt ihn einen Hinweis, keine Garantie: Sie verspricht nicht, dass die Ressource bis genau zu diesem Zeitstempel funktioniert, und sie sagt nichts darüber, wie ein Ausfall danach aussehen wird. Aufrufer können einen 4xx, eine Weiterleitung oder gar keine Antwort bekommen; der Header unterscheidet nicht. Ein Zeitstempel, der schon in der Vergangenheit liegt, bedeutet “jetzt, oder jederzeit” statt eines Fehlers im Wert. Nichts davon wird vom Protokoll erzwungen. Ein Client, der den Header nie liest, verhält sich genau wie immer und erfährt vom Verschwinden der Ressource auf demselben Weg, wie er es ohnehin erfahren hätte.

Wann solltet ihr ihn tatsächlich senden?

Erst wenn die Ressource wirklich aufhören wird zu antworten, nicht schon, wenn sie nur nicht mehr die empfohlene Wahl ist. Die RFC macht deutlich, dass Deprecation in zwei Stufen abläuft, und das Sunset-Header-Feld gehört nur zur zweiten: Während der ersten Stufe, der Ankündigung, dass eine Version nicht mehr bevorzugt wird, bleibt die API voll funktionsfähig, und das Header-Feld gilt dort nicht. Es gilt erst, sobald die Version tatsächlich geplant ist, nicht mehr zu antworten.

Das entspricht direkt dem Deprecation-Zeitplan: Der Deprecation-Header geht ab Tag eins raus, im Ankündigungsschritt; Sunset beschreibt das Datum, an dem das alte Verhalten tatsächlich endet, und das ist dasselbe Datum, das der vierstufige Zeitplan als Retirement bezeichnet. Sunset schon an Tag eins zu senden, ist nicht falsch, da das Datum dann schon feststeht, aber ihn zu senden, ohne vorher eine Deprecation angekündigt zu haben, oder ihn für eine Version zu setzen, deren Abschaltung ihr noch gar nicht beschlossen habt, sagt Aufrufern etwas, das ihr selbst noch nicht entschieden habt.

Interagiert er mit Caching?

Nein, und die RFC sagt das direkt: Sunset und HTTP-Caching lösen voneinander unabhängige Probleme und sollten als komplementär gelesen werden, nicht als überlappend. Caching-Header sagen, wann eine zwischengespeicherte Kopie sicher wiederverwendet werden kann; Sunset sagt nichts über den aktuellen Zustand der Ressource, nur dass die Ressource selbst aufhören wird zu existieren. Eine Antwort kann bis zu dem Moment, in dem ihr Sunset eintritt, vollständig cachebar sein. Verwendet das eine nicht als Näherung für das andere, und geht nicht davon aus, dass ein langes max-age ein nahendes Sunset-Datum aufhebt, oder umgekehrt.

Kann ein Header mehr als einen Endpunkt betreffen?

Der Header gilt für die Ressource, die ihn zurückgegeben hat, aber die RFC erlaubt einem Dienst, einen weiteren Geltungsbereich zu dokumentieren: Ein Sunset-Datum auf der Home-Ressource einer API kann so definiert werden, dass die gesamte API verschwindet, nicht nur diese eine URL. Der Haken ist, dass das nur für Aufrufer funktioniert, die eure Scoping-Regel bereits kennen. Ein Aufrufer, der den Header wörtlich liest, sieht einen Sunset nur für die eine angeforderte Ressource und sonst nichts, also muss ein weiterer Geltungsbereich irgendwo aufgeschrieben stehen, wo ein Aufrufer ihn finden kann, nicht bloß impliziert sein.

Was sollte zusätzlich zum Header mitgeschickt werden?

Ein Link dahin, wo das Retirement erklärt wird. RFC 8594 registriert dafür eine eigene sunset-Link-Relation: Sie verweist auf eine Ressource, die die Retirement-Richtlinie, das bevorstehende Datum oder den Migrationsweg beschreibt, getrennt vom bloßen Zeitstempel des Headers.

HTTP/1.1 200 OK
Sunset: Sat, 31 Dec 2028 23:59:59 GMT
Link: <https://example.com/docs/sunset-policy>; rel="sunset"

Diesen Link auf eure eigenen Changelog-Beispiele oder eine eigene Migrationsseite zu setzen, macht aus einem Header, den fast kein Client-Code prüft, etwas, das ein Mensch, der tatsächlich nachschaut, sofort findet. Kombiniert es mit der successor-version-Relation aus den Deprecation-Headern und ein Aufrufer bekommt allein aus der Antwort sowohl, wohin er gehen soll, als auch, was diese Version ersetzt.

Wie sieht das Ganze End-to-End aus?

Angenommen, v1 verschwindet am 1. März 2027. Die Deprecation-Ankündigung am ersten Tag fügt jeder v1-Antwort Deprecation und Link: rel="successor-version" hinzu, gemäß den Deprecation-Headern, hält aber mit Sunset zurück, bis das Retirement-Datum wirklich feststeht statt nur ein Platzhalter zu sein. Sobald das der Fall ist, trägt jede v1-Antwort:

HTTP/1.1 200 OK
Deprecation: @1756425600
Sunset: Mon, 01 Mar 2027 00:00:00 GMT
Link: <https://api.example.com/v2/reports>; rel="successor-version"
Link: <https://example.com/docs/sunset-policy>; rel="sunset"

Das Gateway oder Monitoring eines Aufrufers kann auf jeden Header unabhängig reagieren: Deprecation sagt, dass eine neuere Version existiert, Sunset sagt, dass diese hier eine Uhr hat. Keiner der beiden Header muss sich vor dem 1. März ändern; was sich ändert, ist die Antwort selbst, am Tag selbst und während geplanter Brownout-Fenster davor.

Ändert ein Brownout, was der Header sagt?

Der Header-Wert selbst muss sich für einen geplanten Brownout nicht ändern: Das Sunset-Datum bleibt das Sunset-Datum, egal ob die Ressource davor zeitweise ausfällt oder nicht. Was sich ändert, ist die Antwort, nicht der Header. Kurze Fenster mit 410 Gone in den Wochen vor dem angekündigten Datum einzuplanen, wie API-Abkündigung beschreibt, macht aus dem ersten Kontakt eines Aufrufers mit dem Ausfall eine Generalprobe statt des Ernstfalls an dem Tag, an dem das Datum des Headers eintrifft.

FAQ

Lesen echte HTTP-Clients oder Tools den Sunset-Header überhaupt? Auf Client-Seite selten. Sein Wert liegt vor allem bei denen, die Infrastruktur zwischen euch und dem Aufrufer betreiben: Ein API-Gateway oder ein Monitoring-Tool, das ihr so konfiguriert, dass es auf den Header achtet, kann euer eigenes Team oder das eines Partners weit bevor der Code des Aufrufers je etwas bemerkt, alarmieren. Behandelt ihn als Signal, um das ihr Tooling baut, nicht als eines, von dem ihr annehmen könnt, dass die Gegenseite es bereits hat.

Ist Sunset dasselbe wie Cache-Control: max-age? Nein. max-age geht darum, wie lange eine zwischengespeicherte Kopie gültig bleibt; Sunset geht darum, wann die Ressource überhaupt aufhört zu existieren. Eine Antwort kann ein kurzes max-age und ein Jahre entferntes Sunset-Datum tragen, oder umgekehrt, und keiner der beiden Header schränkt den anderen ein.

Kann ich Sunset für ein einzelnes verschwindendes Feld senden, nicht für den ganzen Endpunkt? Nein, der Header ist auf die Ressource bezogen, also auf die URL, nicht auf ein Feld innerhalb ihres Response-Bodys. Für ein Feld, einen Parameter oder einen Enum-Wert, der verschwindet, während der Endpunkt selbst bestehen bleibt, verwendet stattdessen den Deprecation-Header und einen Changelog-Eintrag; API-Abkündigung behandelt genau diese Art der Ankündigung.

Was, wenn sich das Sunset-Datum verschieben muss? Aktualisiert den Header-Wert und sagt das im Changelog-Eintrag, der es ursprünglich angekündigt hat; ein veröffentlichtes Datum stillschweigend zu ändern, ist genau der Weg, auf dem ein Aufrufer entscheidet, dass keines eurer Daten echt ist. Die RFC beschreibt den Wert genau deshalb als Hinweis, weil sich Daten manchmal verschieben, aber ein verschobenes Datum ohne Erklärung kostet euch auch das nächste.


Die technischen Aussagen in diesem Artikel wurden nicht unabhängig geprüft. Wenn etwas nicht stimmt, sagen Sie es uns, und wir korrigieren es.

Mehr bei changeloop: Entwicklerdokumentation, Changelog-Beispiele

changeloop
Das Team hinter einem Changelog, das den Kreis schließt. Ihre Nutzer fragen, Ihr Team liefert, und wer gefragt hat, erfährt davon.