CodeGym /Kurse /Spring REST & MVC /Stateless, safe und Idempotenz bei HTTP

Stateless, safe und Idempotenz bei HTTP

Spring REST & MVC
Level 2, Lektion 4
Verfügbar

1. Stateless, safe, idempotency: Anfrage-Wiederholungen

Wenn du noch nie mit Anfrage-Wiederholungen zu tun hattest, herzlichen Glückwunsch: Entweder fängst du gerade erst an, oder dein Internet ist so stabil, dass dein Anbieter dir bereits ein Denkmal aufstellen sollte. In der Realität wird ein und dieselbe Anfrage leicht mehrfach gesendet — wegen eines Timeouts, wegen eines „Doppelklicks" oder wegen einer automatischen Wiederholung in der Client-Bibliothek. Und genau hier hören drei HTTP-Konzepte auf, „Theorie aus dem Lehrbuch" zu sein, und werden zum praktischen Sicherheitsgurt.

Stell dir folgende Szene vor: Der Client hat eine Anfrage gesendet, der Server hat seine Arbeit erledigt, aber die Antwort ist irgendwo verloren gegangen. Der Client weiß nicht, ob die Aktion ausgeführt wurde, und entscheidet sich, es zu wiederholen. Die Frage: Ist die Wiederholung sicher? Bricht sie nichts? Erzeugt sie kein Duplikat? Führt sie „dieselbe Sache nochmal aus" dort, wo „nochmal" bereits zweimal bedeutet?

Damit wir nicht ins Blaue raten (was übrigens auch manchmal „per Timeout abstürzt"), gibt uns HTTP drei Eigenschaften:

  • stateless hilft zu verstehen, dass der Server „den vorherigen Schritt des Gesprächs nicht erinnert" — jede Anfrage muss eigenständig sein.
  • safe methods helfen, Lesen von Zustandsänderungen zu unterscheiden, damit zufällige Wiederholungen, Prefetch oder Caching nicht zu Datenänderungen werden.
  • idempotency hilft, im Voraus zu verstehen, was passiert, wenn man eine Anfrage wiederholt, und ob der Client das bedenkenlos tun kann.

Bisher haben wir die Form des HTTP-Austauschs besprochen: Anfrage, Antwort, Status, Header, Datenformat. Aber sobald im Netzwerk Timeouts und Wiederholungen auftreten, reicht die Form allein nicht mehr aus. Man muss verstehen, was die Methode selbst über ihr Verhalten verspricht: Ändert sie den Zustand? Kann man sie wiederholen? Muss der Server den vorherigen Schritt des Clients erinnern?

2. Stateless: Jede Anfrage ist eigenständig

Das Wort stateless klingt manchmal so, als müsse der Server „gedächtnislos" sein und wie ein Goldfisch leben: Anfrage gesehen — geantwortet — vergessen. Das verwirrt Anfänger fast immer. In der Praxis bedeutet stateless nicht, ob der Server Aufgaben im Speicher hält, sondern ob er den Gesprächskontext zwischen Anfragen speichert. Und für das API-Design ist das entscheidend.

Stateless: Anfrage-Kontext, nicht „der Server speichert nichts"

Lass uns sofort den größten Mythos entschärfen: stateless bedeutet nicht „der Server hat überhaupt keinen Zustand". Der Server kann Aufgaben, Kommentare, Anhänge — was auch immer — speichern (in unserem Lernprojekt ist das ein In-Memory-Speicher). Stateless bedeutet etwas anderes: Jede einzelne HTTP-Anfrage muss alles enthalten, was für ihre Verarbeitung nötig ist, und der Server darf nicht von der „vorherigen Anfrage dieses Clients" als Dialog-Schritt abhängig sein.

Hilfreich ist folgende Vorstellung: Der Zustand einer Ressource (z. B. eine Aufgabe) ist normal und erwartet. Aber der Zustand der Interaktionssitzung — „der Client sieht gerade die Aufgabenliste, sein Filter ist so-und-so, er ist auf Seite 3" — das ist bereits „Gesprächsgedächtnis". Und klassisches Stateless-HTTP setzt voraus, dass ein solches Gedächtnis zwischen Anfragen nicht existiert.

Eine kleine Analogie: Du kannst zuhause Lebensmittel im Kühlschrank lagern (Ressourcenzustand), aber das bedeutet nicht, dass der Kurier sich erinnern muss, was du gestern bestellt hast (Dialogzustand). Jede neue Bestellung muss die Adresse und die Artikelliste enthalten — sonst fängt der Kurier an zu „raten", und Raten in der IT endet in der Regel mit einem Bug-Report.

Stateless konkret: ein Client, zwei Anfragen

Jetzt machen wir den nützlichsten „Illusionsbrechenden Test". Nehmen wir zwei Anfragen von ein und demselben Client. In der ersten bittet er um die Aufgabenliste mit dem Status TODO. In der zweiten — nur um die Aufgabenliste.

# Wichtig: Der Filter wird in dieser Anfrage explizit übergeben und „klebt" nicht an den folgenden
GET /api/v1/tasks?status=TODO HTTP/1.1
Accept: application/json
# Wichtig: Hier gibt es keinen Filter — der Server ist nicht verpflichtet, sich zu „erinnern", dass vor einer Minute TODO war
GET /api/v1/tasks HTTP/1.1
Accept: application/json

Manchmal denkt ein Anfänger: „Aber das ist doch derselbe Benutzer, er hat gerade TODO angefragt, also sollte die zweite Anfrage den Filter ‚erinnern'." HTTP antwortet darauf: „Muss sie nicht. Und überhaupt bin ich ein Protokoll, kein persönliches Notizbuch."

Wenn in der zweiten Anfrage kein status=TODO vorhanden ist, ist der Server nicht verpflichtet (und wird in der Regel nicht), den Filter „beizubehalten". Nicht weil der Server bösartig ist, sondern weil der Vertrag so verständlicher ist: Alles, was wichtig ist, muss explizit in der Anfrage angegeben werden.

Wenn man es ganz vereinfacht: Stateless bedeutet, dass man dem Server nicht sagen kann „du weißt doch, was ich meine". Man muss alles vollständig angeben. Ja, sogar wenn es dir so vorkommt, als hättet ihr das schon vor einer Minute „besprochen".

Stateless und Task Tracker API: Filter, Seiten, Sortierungen

Im Projekt Task Tracker API werden wir viele Szenarien haben, die wie „ein Gespräch" aussehen: Erst bittest du um eine Liste, dann präzisierst du den Filter, dann wechselst du die Seite. Und hier zwingt Stateless dazu, den Vertrag so zu gestalten, dass jede Anfrage eigenständig ist.

Zum Beispiel kann der Client Aufgaben mit dem Status IN_PROGRESS und gleichzeitig eine bestimmte Seite anfordern:

# Wichtig: Sowohl Filter als auch Paginierung werden in jeder Anfrage explizit übergeben
GET /api/v1/tasks?status=IN_PROGRESS&page=0&size=20 HTTP/1.1
Accept: application/json

Wenn der Client eine Sekunde später die nächste Seite anfordert, darf er nicht davon ausgehen, dass der Server sich status=IN_PROGRESS „gemerkt" hat. Die korrekte Anfrage sieht also so aus:

GET /api/v1/tasks?status=IN_PROGRESS&page=1&size=20 HTTP/1.1
Accept: application/json

Ja, das ist etwas ausführlicher. Aber der Vertrag wird dadurch nicht zur Telepathie.

Und hier ergibt sich ein wichtiger praktischer Schluss: stateless macht die API einfacher zu skalieren, zu testen und zu verstehen. Jede Anfrage kann einzeln herausgenommen werden — aus Logs, aus einer .http-Datei, aus dem Postman-Verlauf — und man kann verstehen, was sie bedeutet, ohne das „vorherige Kapitel des Romans" aufzuschlagen.

3. Safe methods: Lesen ohne Zustandsänderung

Nach stateless taucht normalerweise die nächste Frage auf: „Okay, die Anfrage ist eigenständig. Kann man sie auch ohne Angst wiederholen, dass sich etwas ändert?" Hier kommt das Konzept der safe methods ins Spiel. Das hat nichts mit Sicherheit im Sinne von „sicher / nicht sicher" zu tun, sondern damit, ob die Operation den Zustand auf dem Server ändert. Und das beeinflusst direkt, welche Methoden wir für welche Aktionen wählen.

Was „safe" bedeutet (und warum das nicht „sicher" heißt)

Eine safe method ist eine HTTP-Methode, die ihrer Semantik nach zum Lesen gedacht ist und den Zustand der Ressource auf dem Server nicht verändern sollte. Der wichtigste Vertreter ist GET. Zu safe zählen üblicherweise auch HEAD und OPTIONS.

Wichtig: safe bedeutet nicht „sicher aus Sicht des Zugriffs". Sicherheit (wer lesen und schreiben darf) ist ein separates Thema. Safe bedeutet „ändert den Zustand nicht". Das heißt, GET /api/v1/tasks kann aus Zugriffsicht völlig unsicher sein (wenn dort private Daten stehen), aber es sollte trotzdem safe im Sinne seiner Semantik sein: Es darf keine neue Aufgabe erstellen und keine bestehende ändern.

Noch eine Nuance, die oft überrascht: Safe verbietet keine technischen Nebeneffekte wie Logs, Metriken, Erhöhung des Anfragezählers, Befüllen des Caches. Das ist die „interne Küche" des Servers, die den Sinn der Ressource für den Client nicht verändern sollte. Wenn wir sagen „ändert den Zustand nicht", meinen wir den Zustand der über die API zugänglichen Ressourcen, nicht dass der Server keine Zeile in ein Log schreiben darf.

Wie man die Safe-Semantik bricht (und warum das den Client schmerzt)

Die toxischste Gewohnheit (ja, toxischer als „Ich setze das Passwort auf 1234, ich bin ja in dev") ist es, Änderungen über GET vorzunehmen, weil „man es so einfach im Browser öffnen kann". Zum Beispiel:

# Schlechtes Beispiel: GET soll safe sein, aber hier findet eine Zustandsänderung statt (Löschen)
GET /api/v1/tasks/42/delete HTTP/1.1

oder

# Schlechtes Beispiel: GET soll safe sein, aber hier findet eine Zustandsänderung statt (Abschließen)
GET /api/v1/tasks/42/complete HTTP/1.1

Selbst wenn du REST-Design noch nicht diskutierst, liegt hier ein Problem auf HTTP-Ebene: GET soll safe sein, aber diese Anfragen ändern eindeutig den Zustand.

Warum das wirklich gefährlich ist und nicht nur „Krittelei an Standards":

- Ein Proxy oder Browser kann GET cachen. Caching ist eine normale Optimierung für Lesezugriffe. Aber wenn GET den Zustand ändert, wird der Cache zum „Verhaltens-Randomizer".

- Client-Systeme können Prefetch (Vorabladen) von GET-Links durchführen. Das bedeutet, du hast irgendwo einen Link angezeigt, und der Browser hat beschlossen, ihn „vorab vorzubereiten". Und plötzlich wurde die Aufgabe „von alleine gelöscht".

- Manche automatischen Bots und Scanner folgen gerne GET-Links, besonders wenn sie irgendwo „aufgetaucht" sind. Wenn GET den Zustand ändert, gibst du dem Bot buchstäblich die Schaltfläche „Zerstör mir die Daten".

Die Regel ist also einfach und rein praktisch: Wenn du eine API siehst, bei der GET etwas verändert, ist das kein „interessanter Architektur-Fund", sondern eine zukünftige Quelle für Nachtanrufe.

Safe-Methoden in unserem Projekt: Beispiele für korrekte GET-Anfragen

Im Kontext der Task Tracker API sind safe-Anfragen Leseanfragen. Zum Beispiel die Aufgabenliste oder eine einzelne Aufgabe nach ID lesen — das ist der Klassiker.

# Safe: Das Lesen der Aufgabenliste darf den Ressourcenzustand nicht ändern
GET /api/v1/tasks HTTP/1.1
Accept: application/json
# Safe: Das Lesen einer konkreten Aufgabe darf nichts am Server „verstellen"
GET /api/v1/tasks/42 HTTP/1.1
Accept: application/json

Selbst wenn du sie 10 Mal hintereinander sendest, erwartest du, dass sich die Aufgaben dadurch nicht ändern. Ja, die Antworten können sich im Laufe der Zeit unterscheiden (z. B. hat jemand anderes die Aufgabe aktualisiert oder du selbst hast sie mit einer anderen Anfrage geändert), aber das GET selbst sollte nicht der Grund für eine Änderung sein.

Ganz konkret: safe bedeutet, dass du lesen kannst, ohne zu befürchten, dass „das Lesen das Objekt kaputt macht". In der Programmierung lieben wir das intuitiv: Ein Aufruf von getTitle () sollte nicht plötzlich setTitle ("kaputt") aufrufen. In HTTP ist es genau dieselbe Idee, nur auf Netzwerkebene.

4. Idempotency: Anfrage-Wiederholung und Endzustand

Wenn safe sagt „die Anfrage ändert den Zustand nicht", beantwortet idempotency eine kniffligere Frage: „Und wenn die Anfrage den Zustand doch ändert — was passiert bei einer Wiederholung?" Und hier versucht HTTP erneut, uns vor dem Chaos zu retten, das durch Timeouts, Wiederholungen und „Hoppla, ich habe zweimal gedrückt" entsteht. Idempotenz klingt einschüchternd, bedeutet aber im Grunde einfach „Wiederholung macht es nicht schlimmer".

Idempotenz: formuliert ohne Magie

Eine idempotent method ist eine Methode, bei der die Wiederholung ein und derselben Anfrage zum gleichen Endzustand auf Serverseite führt.

Achte auf die Worte „Endzustand". Das ist wichtiger als „dieselbe Antwort". Die Antworten können sich in Kleinigkeiten, Zeit, Headern unterscheiden. Aber der Kern ist: Nach N Wiederholungen befindet sich der Server im gleichen Zustand wie nach 1 Wiederholung.

Idempotent: "Mach, dass es so und so aussieht"
Not idempotent: "Führe die Aktion erneut aus"
  • PUT — bedeutet normalerweise „Mach, dass die Ressource so aussieht". Wiederholen ist möglich.
  • DELETE — bedeutet normalerweise „Mach, dass die Ressource nicht mehr existiert". Wiederholen ist möglich.
  • POST — bedeutet oft „Erstelle eine neue Ressource". Wiederholen bedeutet eine weitere erstellen. Und hier beginnt der Spaß mit Duplikaten.

Und noch ein sehr wichtiger Anti-Mythos: Idempotenz in HTTP bedeutet nicht „immer derselbe Status und Body". In der Praxis können Wiederholungen unterschiedliche Antworten haben, aber der Vertrag muss trotzdem sinnvoll und vorhersehbar bleiben.

PUT und DELETE als „Paradebeispiele" der Idempotenz

Um Idempotenz zu spüren, schaut man am besten auf PUT und DELETE. Sie sind wie Lehrbeispiele — nahezu perfekt.

PUT bedeutet in seiner einfachen Form „Ersetze die Darstellung der Ressource durch diese hier". Angenommen, wir möchten, dass Aufgabe 42 den Titel "Write docs" hat.

# Idempotent: Die Wiederholung von PUT bringt die Ressource in denselben Zustand (fügt keinen weiteren Titel hinzu)
PUT /api/v1/tasks/42 HTTP/1.1
Content-Type: application/json

{"title":"Write docs"}

Wenn du diese Anfrage noch einmal sendest, ist der Endzustand der Ressource immer noch: Titel = "Write docs". Kein zweites „Write docs" erscheint. Das ist Idempotenz.

DELETE bedeutet „Mach, dass die Ressource nicht mehr existiert". Zum Beispiel:

# Idempotent bezüglich des Endzustands: Nach beliebig vielen Wiederholungen bleibt die Ressource gelöscht
DELETE /api/v1/tasks/42 HTTP/1.1

Das erste DELETE löscht die Aufgabe. Das zweite DELETE… und hier beginnt der interessante Teil des Designs. Dem Sinn nach ist der Endzustand derselbe: Die Aufgabe existiert nicht. Aber wie zu antworten ist — da gibt es Varianten. Manche geben 404 Not Found zurück (es gibt nichts mehr zu löschen), andere 204 No Content (das Ergebnis ist dasselbe: Die Ressource existiert nicht). Wichtig ist, dass die Wiederholung nicht zu „noch stärkerem Löschen" führen sollte, denn es gibt nichts mehr zu löschen. Die Ressource ist bereits weg.

Das innere „Gefühl" lässt sich auf Java übertragen: Wenn du map.remove(key) aufrufst, entfernt das zweite remove nichts „weiteres". Es gibt entweder null oder false zurück, aber der Zustand der Map wird nach dem zweiten Mal nicht „noch gelöschter".

Warum POST normalerweise nicht idempotent ist (und was daraus folgt)

POST bedeutet meistens „Erstelle eine neue Ressource innerhalb der Collection". Daher bedeutet die Wiederholung „desselben POST" normalerweise das Erstellen einer weiteren Ressource.

# Normalerweise nicht idempotent: Die Wiederholung von POST kann ein Duplikat der Ressource erstellen
POST /api/v1/tasks HTTP/1.1
Content-Type: application/json

{"title":"Write docs"}

Wenn der Client das zweimal sendet, kann der Server völlig korrekt zwei verschiedene Aufgaben mit unterschiedlichen IDs erstellen. Und das ist kein „Server-Fehler". Das ist die erwartete Semantik von POST.

Warum ist das wichtig? Weil Anfrage-Wiederholungen wirklich vorkommen. Der Client hat vielleicht wegen eines Timeouts keine Antwort bekommen und die Anfrage wiederholt. Der Benutzer hat vielleicht zweimal auf „Erstellen" gedrückt. In einer normalen Welt (also einer Welt, in der das Netzwerk nicht perfekt ist) ist POST eine Risikozone für Duplikate.

Manchmal wirst du Lösungen begegnen, die POST über zusätzliche Mechanismen idempotent machen, beispielsweise über einen Idempotency Key im Header oder über eine ID, die der Client selbst generiert. Aber das ist schon das Thema „Wie kämpft man gegen Duplikate in einem verteilten System" und kann für die erste Begegnung überflüssig sein. Im Rahmen dieser Lektion ist es wichtig, das Grundprinzip zu verstehen: POST kann nicht automatisch als idempotent angesehen werden, und der Client muss bei der Wiederholung vorsichtig sein.

Übrigens, lass uns einen nützlichen Gedanken festhalten: Wenn du eine Methode für einen Endpoint wählst, wählst du nicht nur „wie die API schön aussieht", sondern auch welche Eigenschaften der Client erhält. Client-seitige Wiederholungen sind keine Fantasie, sondern Realität. Und die Methode beeinflusst direkt, ob eine solche Wiederholung sicher ist.

Mini-Tabelle: safe vs. idempotent für gängige Methoden

Damit man nicht alles wie ein Gedicht im Kopf behalten muss, ist eine kleine Matrix praktisch. Sie ist nicht die „einzige Wahrheit", sondern die typische Semantik in den meisten APIs.

HTTP method Safe Idempotent Intuitiver Sinn
GET ja ja Darstellung einer Ressource/Collection lesen
HEAD ja ja Nur Metadaten lesen (ohne Body)
OPTIONS ja ja „Was ist möglich?" herausfinden (technisch)
PUT nein ja Ressource in den angegebenen Zustand bringen
DELETE nein ja Welt in den Zustand „Ressource existiert nicht" bringen
POST nein normalerweise nein Neue Ressource erstellen / Verarbeitung starten
PATCH nein nicht garantiert Ressource teilweise ändern (kann idempotent sein, hängt vom Vertrag ab)

Und noch ein kurzer Satz, der oft vor Verwirrung bewahrt: safe bedeutet fast immer idempotent, denn wenn eine Methode nichts ändert, ändert auch die Wiederholung nichts. Aber idempotent bedeutet nicht safe, denn DELETE ändert den Zustand, obwohl man ihn grundsätzlich wiederholen kann.

5. Wie diese Eigenschaften den Vertrag beeinflussen

Die drei Konzepte — stateless, safe methods, idempotency — klingen theoretisch, bis man versucht, sich einen echten Client vorzustellen, der „im Internet lebt": mit Timeouts, wiederholten Anfragen, schlechtem WLAN und dem Benutzerverhalten „gedrückt, aber nicht sicher, nochmal gedrückt". In diesem Moment wird plötzlich klar: Diese Eigenschaften sind keine Philosophie, sondern eine Anleitung, wie man eine API baut, die man nutzen kann.

Client-seitige Retries, Timeouts und Doppelklicks: Woher Wiederholungen kommen

Die häufigste Quelle für Wiederholungen ist ein banaler Timeout: Der Client hat eine Anfrage gesendet und bekommt nicht schnell eine Antwort. Der Client muss eine Entscheidung treffen: weiter warten oder wiederholen. Und manchmal wiederholt die Client-Bibliothek (oder ein Gateway zwischen Client und Server) automatisch.

flowchart LR
    C[Client] -->|"1) Anfrage"| S[Server]
    S -->|"2) Antwort"| C
    C -->|"Timeout: keine Antwort sichtbar"| C
    C -->|"3) Anfrage wiederholen"| S

In der Praxis konnte der Server die erste Anfrage erfolgreich verarbeitet haben, aber die Antwort „kam nicht an". Dann ist die Wiederholung nicht mehr „einen erneuten Versuch starten", sondern „dasselbe ein zweites Mal tun". Und hier stoßen wir wieder auf die Eigenschaften der Methoden.

  • GET kann man normalerweise bedenkenlos wiederholen: Die Methode ist safe und idempotent.
  • PUT und DELETE kann man in Bezug auf den Endzustand normalerweise auch bedenkenlos wiederholen: Sie sind nicht safe, aber idempotent.
  • POST zu wiederholen ist gefährlich: Es kann ein Duplikat entstehen.

Und stateless fügt noch einen wichtigen Gedanken hinzu: Wenn dein Szenario aus mehreren Anfragen besteht, muss jede Anfrage alle nötigen Informationen enthalten. Eine Anfragenwiederholung darf nicht davon abhängen, was „einen Schritt vorher" war.

Praktische „Entscheidungsmatrix" für Methoden in der Task Tracker API

Jetzt verbinden wir alles mit dem Projekt, aber streng auf HTTP-Semantik-Ebene, ohne in Implementierungsdetails einzutauchen. Nehmen wir ein paar typische Operationen rund um Aufgaben.

Wenn der Client eine Aufgabenliste haben möchte, macht er GET /api/v1/tasks. Das ist safe und idempotent. Der Client kann solche Anfragen wiederholen, die Seite aktualisieren, Daten erneut abrufen — und der Vertrag bleibt verständlich.

Wenn der Client eine einzelne Aufgabe möchte, macht er GET /api/v1/tasks/{taskId}. Ebenfalls safe und idempotent.

Wenn der Client eine Aufgabe löschen möchte, macht er DELETE /api/v1/tasks/{taskId}. Das ist nicht safe, aber idempotent. Das bedeutet: „Löschen wiederholen" sollte nicht zu „noch etwas löschen" werden. Der Endzustand ist derselbe: Die Aufgabe existiert nicht.

Wenn der Client eine Aufgabe erstellen möchte, macht er POST /api/v1/tasks. Das ist normalerweise nicht idempotent: Eine Wiederholung kann eine zweite Aufgabe erstellen. Der Client muss das verstehen und vorsichtig mit der Wiederholung sein. Auf Vertragsebene zeigt sich das sogar in den Statuscodes (wir erinnern uns an die Lektion über Statuscodes): Die Erstellung gibt normalerweise 201 Created zurück, und das ist ein „Ereignis", das man nicht versehentlich zweimal erhalten möchte.

Und noch abschließend, um den Unterschied zwischen safe und idempotent zu festigen, ist es nützlich, ein einfaches Satzpaar auszusprechen. GET ist gut darin, dass seine Wiederholung nichts ändern sollte. PUT und DELETE sind gut darin, dass ihre Wiederholung den Endzustand nicht verschlechtern sollte. POST ist gut darin, dass er ehrlich etwas Neues erstellt — aber genau deshalb ist die Wiederholung gefährlich.

Wenn du eine Methode für einen Endpoint wählst, legst du faktisch das Verhalten der Ressource aus Sicht des Clients fest: Kann man sie sicher lesen? Kann man sie wiederholen? Was ist bei einer Wiederholung zu erwarten? Hier ist HTTP nicht mehr Hintergrund, sondern Teil des API-Designs selbst.

6. Typische Fehler beim Umgang mit der HTTP-Semantik

Fehler Nr. 1: stateless als „der Server speichert nichts" verstehen.
Wenn man „stateless" hört, stellt man sich leicht einen Server vor, der überhaupt keine Daten speichert und ständig die Welt neu berechnet. Das ist falsch und führt schnell zu seltsamen Diskussionen wie „REST ist unmöglich, weil der Server Daten speichert". Stateless bezieht sich auf den Anfrage-Kontext: Der Server ist nicht verpflichtet, den „vorherigen Schritt" eines bestimmten Clients zu erinnern. Gleichzeitig ist das Speichern von Aufgaben als Ressourcen völlig normal.

Fehler Nr. 2: Erwarten, dass der Server den „Filter" oder die „Seite" erinnert.
Eine sehr verbreitete Falle: Der Client fragt zuerst GET /tasks?status=TODO, dann macht er GET /tasks?page=1 und wundert sich, warum auf der zweiten Seite keine TODO-Aufgaben mehr sind. HTTP-Interaktion ist stateless: Wenn der Filter wichtig ist, muss er in jeder Anfrage vorhanden sein. Sonst ist der Server nicht verpflichtet zu erraten, dass sich „Seite 1" auf den „vorherigen Filter" bezieht.

Fehler Nr. 3: safe und „sicher aus Sicht des Zugriffs" verwechseln.
Safe betrifft die Zustandsänderung. Es geht nicht darum, ob der Client das Recht hat, Daten zu lesen. Man kann GET safe machen, aber gleichzeitig kann der Zugriff darauf eingeschränkt sein (in echten Projekten). Und umgekehrt kann man POST allen zugänglich machen (was eine schlechte Idee wäre), aber er wird trotzdem nicht safe. Vermische nicht „ändert den Zustand nicht" mit „alle dürfen".

Fehler Nr. 4: Änderungen über GET vornehmen, „weil es einfacher ist".
Das ist der Fall, wo Faulheit zu Beginn zu unerwarteten Bugs in der Produktion wird. Wenn GET den Zustand ändert, brichst du die Erwartungen des Clients, brichst die Möglichkeit des Cachings und machst dich anfällig für Prefetch und automatische Link-Prüfungen. Am Ende kann „zufälliges Ansehen eines Links" zu „zufälligem Löschen einer Aufgabe" werden — und das ist keine Ingenieurarbeit mehr, sondern der Stoff für einen Thriller.

Fehler Nr. 5: Denken, dass idempotency „immer dieselbe Antwort" bedeutet.
Die Wiederholung von DELETE kann einen anderen Status zurückgeben (z. B. zuerst 204, dann 404), und das ist nicht unbedingt eine Verletzung der Idempotenz, wenn der Endzustand „Ressource existiert nicht" bleibt. Idempotency betrifft den Endzustand und den Sinn der Operation, nicht den byte-für-byte gleichen Response-Body. Wenn du „absolut dasselbe" erwartest, treibst du dich selbst in eine Ecke.

1
Aufgabe
Spring REST & MVC, Level 2, Lektion 4
Gesperrt
Tabelle der Eigenschaften von HTTP-Methoden
Tabelle der Eigenschaften von HTTP-Methoden
1
Aufgabe
Spring REST & MVC, Level 2, Lektion 4
Gesperrt
Simulation einer wiederholten HTTP-Anfrage
Simulation einer wiederholten HTTP-Anfrage
1
Umfrage/Quiz
HTTP-Grundlagen, Level 2, Lektion 4
Nicht verfügbar
HTTP-Grundlagen
Anfragen, Antworten und Statuscodes
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION