CodeGym /Kurse /Java Server /Sichere und unsichere Operationen in HTTP

Sichere und unsichere Operationen in HTTP

Java Server
Level 9, Lektion 1
Verfügbar

1. Die Idee sicherer Operationen

Wenn Sie gerade erst mit HTTP anfangen, scheint alles recht einfach: es gibt einen Server, eine Anfrage, eine Antwort, und wenn der Status 200 ist, ist alles gut. Aber in der realen Backend-Welt zerbrechen solche naiven Erwartungen schnell und knirschend, wie ein Keks in den Händen eines hungrigen Testers. Anfragen wiederholen sich, der Browser kann die Seite neu laden, ein Proxy kann die Antwort zwischenspeichern, und Sie selbst (oder Ihr Kollege) können „versehentlich“ denselben Endpunkt zweimal aufrufen – und schon haben sich Daten geändert, wo Sie es nicht erwartet haben.

Deshalb gibt es in HTTP das Konzept der sicheren Operationen. Im menschlichen Sinne bedeutet das: „Es gibt solche Aufrufe, bei denen der Client keine Änderung der Daten auf dem Server erwartet.“ Es geht nicht um „Höflichkeit“ oder „guten Ton“. Es geht darum, dass ein großer Teil der Werkzeuge rund um HTTP (Browser, Caches, Proxies, Clients, Monitoring) stillschweigend voraussetzt: Wenn eine Operation sicher ist, kann sie wiederholt, vorab angefordert, gecached werden – und die Welt explodiert nicht.

Stellen Sie sich nun vor, Sie haben einen „trickreichen“ GET erstellt, der tatsächlich ein Buch zur Leseliste hinzufügt. Der Benutzer lädt die Seite neu – das Buch wird noch einmal hinzugefügt. Ein Proxy wiederholt die Anfrage aufgrund eines Netzwerkfehlers – wieder hinzugefügt. Sie führen einen Smoke-Test durch und klicken „ein bisschen“ zweimal auf dieselbe Anfrage – und dann wundern Sie sich, warum Sie in Ihrer Leseliste zehn gleiche „Clean Code“ haben. Das ist der Moment, in dem der Backend für schlechte Verträge rächt.

Um die Idee auf Code-Ebene zu spüren (ohne Server, Postman und all das), genügt ein einfaches Beispiel mit „Zustand“ und zwei Methoden – Lesen und Ändern:

import java.util.ArrayList;
import java.util.List;

class ReadingListState {
    // Interner Zustand (das, was sich bei „unsicheren“ Operationen ändert)
    private final List<String> items = new ArrayList<>();

    List<String> getItems() {               // „sichere“ Operation (Lesen)
        // Wichtig: eine Kopie zurückgeben, damit der aufrufende Code die Liste nicht von außen ändern kann
        return List.copyOf(items);
    }

    void addItem(String title) {            // „unsichere“ Operation (Änderung)
        // Jedes Hinzufügen/Löschen/Aktualisieren ist eine Zustandsänderung
        items.add(title);
    }
}

Und hier ist es wichtig, dieses Thema nicht mit stateless zu vermischen. Stateless beantwortet die Frage, ob der Server die aktuelle Anfrage ohne versteckte Gesprächshistorie verstehen kann. Safe/unsafe beantwortet eine andere Frage: Ändert diese Anfrage den Zustand der Ressource? Daher ist eine Operation, die gleichzeitig stateless und unsafe ist, völlig normal: zum Beispiel ein korrekter POST, bei dem alle Daten explizit übergeben werden, aber das Ergebnis dennoch eine Änderung der Ressource ist.

2. Merkmale einer sicheren Operation

Wenn das Wort „sicher“ auftaucht, macht das Gehirn eines Anfängers oft einen logischen Salto und beginnt Dinge zu hören wie: „Das bedeutet, sie ist immer erfolgreich“ oder „das bedeutet, sie kann keinen Fehler verursachen“. Leider nein. Safe handelt nicht von „Erfolg“, sondern von der Abwesenheit einer erwarteten Datenänderung.

Streng angewandt gesprochen, ist eine sichere Operation eine Operation, nach der der Client erwarten darf: „ich habe nichts verdorben und nichts geändert“. Dabei kann der Server ruhig mit einem Fehler antworten, die Ressource nicht finden, abstürzen – aber die Idee der sicheren Operation spricht über die Semantik des Aufrufs, nicht über eine Ergebnisgarantie.

Noch etwas ist wichtig: Sicherheit wird durch den Effekt bestimmt, nicht durch den „Namen“ oder die „Atmosphäre“ der Methode. Man kann eine Methode getSomethingVeryImportant() schreiben, die im Inneren die Hälfte der Daten löscht, und formal wird es ein get… sein, aber im Wesentlichen ist es ein Weltzerstörer. Genauso in HTTP: wenn Sie GET nehmen und tatsächlich den Zustand der Ressource ändern – haben Sie den Sinn verletzt, selbst wenn Sie einen schönen Status zurückgeben.

Eine Mini-Regel, die man sich wie ein Mantra wiederholen sollte: „Sicherheit wird dadurch bestimmt, ob sich der Zustand der Ressource ändert, nicht dadurch, welche Methode Sie dafür genannt haben.“

Schauen Sie sich eine kleine „Gesundheitsprüfung“ im Code an – sie handelt nicht von echter Validierung, sondern davon, wie der Kopf denken sollte:

class OperationSemantics {

    static boolean isSafe(boolean changesServerState) {
        // Safe == ändert den Zustand auf dem Server nicht
        return !changesServerState;
    }

    public static void main(String[] args) {
        // Im Beispiel zeigen wir einfach die Logik: ändern -> unsafe, nicht ändern -> safe
        System.out.println(isSafe(false));  // true
        System.out.println(isSafe(true));   // false
    }
}

Natürlich übergeben Sie in der Realität kein Flag changesServerState in einer HTTP-Anfrage. Aber Sie als Entwickler sollten sich ehrlich die Frage beantworten können: „Ändert dieser Endpoint Daten oder nicht?“ Wenn ja – ist es unsafe. Wenn nein – ist es safe.

Und hier taucht eine feine Nuance auf, die oft verwirrt: „Was ist mit Logs, Metriken, Zählern, der letzten Zugriffszeit?“. Logs und Metriken werden fast immer als akzeptabler „technischer“ Nebeneffekt betrachtet: Sie ändern nicht den Geschäftszustand der Ressource und sollten nicht beeinflussen, was der Client in der Antwort sieht. Aber die Änderung des Buchstatus auf IN_PROGRESS beim Anzeigen ist bereits eine Geschäftsänderung und bricht den Sinn einer safe-Operation. Im fünften Abschnitt werden wir darauf näher eingehen, denn genau dort leben normalerweise die ärgerlichsten Bugs.

3. Safe und HTTP-Methoden

Wir kennen bereits die grundlegenden HTTP-Methoden, und Sie könnten den Eindruck haben, dass safe/unsafe einfach „ein Synonym für GET und nicht-GET“ ist. In erster Näherung kommt das der Wahrheit nahe, und genau deshalb ist das Thema nützlich: Es hilft, schnell die Methode nach dem Sinn auszuwählen. Aber es ist wichtig zu verstehen, dass safe/unsafe Semantik ist, und Methoden sind Werkzeuge zum Ausdruck dieser Semantik.

Im klassischen angewandten HTTP-Denken nimmt man normalerweise an: GET sollte sicher sein, weil es Lesen ausdrückt. POST, PUT, PATCH, DELETE gehören zu den Datenänderungsoperationen, daher sind sie unsicher. Das ist keine „Laune des Standards“, sondern eine Möglichkeit, die API für Clients und die gesamte Infrastruktur vorhersagbar zu machen.

HTTP-Methode Erwartete Rolle Sicher? Kommentar zur Bedeutung
GET Lesen ja Operation sollte den Ressourcenzustand nicht ändern
POST Erstellung/Aktion nein erstellt normalerweise eine Ressource oder löst eine Änderung aus
PUT vollständiger Ersatz nein ändert den Zustand der Ressource (aber oft idempotent)
PATCH teilweise Änderung nein ändert den Zustand der Ressource
DELETE Löschung nein ändert den Zustand der Ressource (oft idempotent)

Jetzt binden wir das an unsere Domäne ReadLater Starter (auch wenn wir noch keinen Server schreiben). Stellen Sie sich vor, wir haben eine lokale reading list API. Welche Operationen gibt es dort in menschlicher Hinsicht?

Wenn der Benutzer die Liste der Bücher ansehen möchte, ist das Lesen und sollte safe sein. Wenn der Benutzer ein Buch hinzufügen möchte, ist das eine Zustandsänderung und es ist unsafe. Wenn der Benutzer den Status eines Buches ändern möchte, ist das ebenfalls unsafe. Das heißt, „Ansehen“ und „Ändern“ sollten durch verschiedene HTTP-Methoden ausgedrückt werden, damit der Client nicht in einer Überraschungswelt lebt.

Sehr bezeichnend ist das Gegenbeispiel – der „schlechte GET, der eine Änderung durchführt“. Es sieht fast immer wie ein „praktischer Hack“ aus, bis die Realität eintritt:

class BadApiIdea {
    // Emulation des Zustands „auf dem Server“
    private int booksCount = 0;

    String getAddBook() {
        // Problem: GET sollte dem Sinn nach lesen, aber hier gibt es einen Nebeneffekt (Änderung)
        booksCount++;
        return "200 OK, count=" + booksCount;
    }
}

Von außen sieht es aus wie „einfach eine Antwort erhalten“. Aber innen ändern Sie den Zustand. Wenn jemand den Aufruf wiederholt – ändert sich der Zustand erneut. Und hier entstehen oft „Geister“-Bugs: anscheinend hat niemand speziell etwas hinzugefügt, aber Bücher sind erschienen.

Auf der Routing-Ebene (wieder ohne echten Server) kann man den Unterschied sogar so darstellen:

class RouterDemo {

    String route(String method, String path) {
        // In einem echten Server würde hier eine Anfrage zerlegt und ein Handler aufgerufen werden.
        // Wichtig ist zu sehen, dass der Sinn der Operation durch die Kombination method + path bestimmt wird.
        if ("GET".equals(method) && "/reading-list".equals(path)) return "list items"; // safe (Lesen)
        if ("POST".equals(method) && "/reading-list".equals(path)) return "add item";  // unsafe (Änderung)
        return "404 Not Found"; // falsche Route
    }
}

Wir schreiben hier keinen echten HttpServer, lesen keinen body, parsen kein JSON. Das ist noch nicht die Zeit. Uns ist jetzt etwas anderes wichtig: Der Sinn wird bereits auf der Ebene „method + path“ ausgedrückt, und das steht in direktem Zusammenhang damit, ob die Operation sicher ist oder nicht.

4. Safe und Idempotenz

Gestern (und früher) haben wir bereits Idempotenz berührt, und hier gibt es eine typische Verwirrung: „Wenn man wiederholen kann, ist es sicher.“ Nein. Und umgekehrt: „Wenn es sicher ist, kann man wiederholen.“ Auch nicht immer. Um nicht durcheinander zu kommen, ist es nützlich im Kopf zu behalten, dass safe und idempotent unterschiedliche Fragen beantworten.

Safe beantwortet die Frage: „Soll die Operation den Zustand der Ressource ändern oder nicht?“ Idempotent beantwortet die Frage: „Wenn ich dieselbe Anfrage mehrmals wiederhole, ist der Effekt derselbe wie bei einmaliger Ausführung?“ Das ähnelt einem Gespräch über Vorsicht und Wiederholbarkeit: Man kann vorsichtig sein (nichts ändern), oder man kann ändern, aber wiederholbar (jedes Mal zum gleichen Zustand führen).

Eine klassische Illustration ist DELETE. Löschen ist eine Zustandsänderung, also ist die Operation unsafe. Aber sie ist oft idempotent: Wenn die Ressource nicht mehr existiert, macht ein erneutes DELETE in der idealen Welt „nichts Neues“ (obwohl die Antwort unterschiedlich sein kann). Ebenso ist PUT normalerweise unsafe, aber idempotent: Sie setzen den vollständigen Zustand der Ressource, und ein wiederholter Aufruf führt zum gleichen Zustand.

Methode Sicher? Idempotent (normalerweise)? Wie liest man das menschlich?
GET ja ja wir lesen, Wiederholung sollte nichts ändern
POST nein nein erzeugt bei Wiederholung oft eine „weitere“ Ressource
PUT nein ja wir bringen die Ressource in einen bestimmten Zustand, Wiederholung ändert das Ergebnis nicht
PATCH nein hängt ab der Effekt hängt davon ab, wie Sie ihn definiert haben
DELETE nein ja wir löschen die Ressource, Wiederholung erzeugt normalerweise keinen neuen Effekt

Und eine kleine Demonstration „an den Fingern“ in Java, um den Unterschied zwischen „ändert/ändert nicht“ und „Wiederholung“ zu spüren:

class IdempotencyToyExample {
    // Einfacher „Ressourcenzustand“
    private String status = "PLANNED";

    void patchToFinished() {            // Zustandsänderung (unsafe)
        // Jeder Aufruf ändert (oder bestätigt) den Zustand: das ist nicht safe
        status = "FINISHED";
    }

    String getStatus() {                // Lesen (safe)
        // Lesen sollte status nicht ändern
        return status;
    }
}

Wenn man getStatus() 10 Mal aufruft – der Zustand ändert sich nicht: safe. Wenn man patchToFinished() 10 Mal aufruft – der Zustand ändert sich (obwohl er nach dem ersten Mal bereits „derselbe“ ist, und daher wird der Effekt der Wiederholung oft als idempotent betrachtet). Das ist der Grund, warum safe und idempotent unterschiedliche Konzepte sind: eines handelt von Änderung, das andere von Wiederholbarkeit des Ergebnisses.

5. Versteckte Änderungen in safe-Operationen

Der heimtückischste Teil des Themas safe/unsafe ist, dass sich die Gefahr oft nicht in der Methode verbirgt, sondern in „nun, wir haben hier nur ein bisschen hinzugefügt…“. So entstehen APIs, die scheinbar „lesen“, aber heimlich den Zustand ändern. Und dann schwört der Entwickler, „nichts dergleichen getan zu haben“, und technisch lügt er nicht einmal – er hat nur „ein bisschen den Zähler korrigiert“. Das Problem ist, dass dies für den Client bereits eine Änderung ist und für die Infrastruktur eine Verletzung der Erwartungen.

Lassen Sie uns zwei Arten von Nebenwirkungen unterscheiden. Es gibt rein technische Effekte: Logging, Metriken, Traces, Limits, Korrelations-IDs. Der Client sieht sie normalerweise nicht als Änderung der Ressource. Wenn Sie GET /reading-list machen und der Server ein Log schreibt „jemand hat die Leseliste aufgerufen“, bricht das nicht die Semantik des Lesens.

Und es gibt Effekte, die den Geschäftszustand der Ressource ändern oder beeinflussen, was der Client sieht. Zum Beispiel machen Sie GET /reading-list/1, und der Server setzt den Buchstatus auf IN_PROGRESS, weil „da wir es geöffnet haben, haben wir mit dem Lesen begonnen“. Das ist bereits Geschäftslogik, und sie ist unerwartet. Oder Sie erhöhen viewsCount und zeigen diese Zahl dem Client – dann ändert ein erneutes GET bereits die Daten, und der Aufruf wird im Sinne des Vertrags unsicher.

Ein schlechtes Beispiel, das „harmlos“ aussieht, aber den Sinn bricht:

class SneakyGet {
    // Der Aufrufzähler ist bereits Teil des beobachtbaren Zustands, wenn wir ihn dem Client zurückgeben
    private int views = 0;

    String getReadingList() {
        // Hauptproblem: GET-Anfrage beginnt, den Zustand der Ressource zu ändern
        views++;
        return "views=" + views;
    }
}

Warum ist das schlecht? Weil jetzt eine wiederholte Anfrage den beobachtbaren Zustand ändert. Der Client kann unterschiedliche Antworten erhalten, nur weil jemand die Seite neu geladen hat. Selbst wenn Sie denken, das sei „nützliche Statistik“, müssen Sie verstehen: Aus Sicht der Semantik einer safe-Operation haben Sie sie unsafe gemacht. Manchmal wünscht das Geschäft tatsächlich Aufrufzähler – das ist normal. Aber dann geben Sie ehrlich zu: „Lesen hat einen Effekt“, und Sie müssen sehr vorsichtig damit leben, dass Wiederholung jetzt nicht „nichts ändert“.

Ein weiterer klassischer Fall – der „GET, der etwas repariert“. Sie korrigieren etwa „on the fly“ inkonsistente Daten, löschen Müll, starten eine Migration, bereinigen Sammlungen. All das sind Änderungen. Und wenn Sie das beim Lesen tun, erschaffen Sie ein System, in dem ein Client zufällig zum „Admin, der die Datenbank repariert“ wird, nur indem er eine Seite öffnet. Das ist lustig, bis zum ersten großen Vorfall.

Die praktischste Regel hier klingt nicht sehr romantisch, rettet aber vor Chaos: Wenn Sie einen GET-Handler schreiben, behalten Sie die Frage im Kopf „welche Felder/Sammlungen/Zustände ändere ich tatsächlich in diesem Code?“. Wenn die Antwort „ich ändere etwas“ ist – halten Sie an und überlegen Sie, ob das wirklich ein Lesen sein sollte.

6. Szenario ReadLater: Lesen und Ändern

Jetzt implementieren wir unseren ReadLater Starter noch nicht als Server, und schon gar nicht schreiben wir vollwertiges CRUD. Aber das ist ein ausgezeichneter Moment, um rechtzeitig die richtigen „Schienen“ im Kopf zu legen, denn später wird die Versuchung groß sein, „schneller und einfacher“ zu machen, und schnell und einfach endet normalerweise damit, dass Sie Ihren eigenen Code um 2 Uhr morgens debuggen und philosophisch aus dem Fenster schauen.

In unserer Domäne gibt es sehr verständliche Aktionen: Liste der Bücher ansehen, ein Buch ansehen, ein Buch hinzufügen, ein Buch aktualisieren, den Status ändern, ein Buch löschen. Wenn Sie sie gedanklich in safe und unsafe aufteilen, fällt es Ihnen leichter, sofort die Methode auszuwählen und nicht zu versuchen, an der Semantik zu „sparen“.

Benutzeraktion Beispiel-Endpoint Sicher? Warum
Liste ansehen GET /api/v1/reading-list ja Lesen, ändert den Zustand der Liste nicht
Einen Eintrag ansehen GET /api/v1/reading-list/1 ja Lesen einer bestimmten Ressource
Eintrag hinzufügen POST /api/v1/reading-list nein erstellt eine neue Ressource, ändert den Zustand
Vollständig aktualisieren PUT /api/v1/reading-list/1 nein ändert die Ressource (auch wenn wiederholbar)
Status ändern PATCH /api/v1/reading-list/1/status nein ändert die Ressource teilweise
Eintrag löschen DELETE /api/v1/reading-list/1 nein löscht die Ressource

Damit dies auf der Ebene des „Codes im Kopf“ keine Abstraktion bleibt, können wir wieder zu einem einfachen Zustand und Operationen zurückkehren:

import java.util.ArrayList;
import java.util.List;

class ReadingList {
    // Speichern den Zustand der Liste „auf dem Server“
    private final List<String> items = new ArrayList<>();

    List<String> list() {                 // safe: nur Lesen
        // Geben eine Kopie zurück, damit das Lesen keine Möglichkeit zur Änderung von außen bietet
        return List.copyOf(items);
    }

    void add(String title) {              // unsafe: Änderung
        // Jedes Hinzufügen ändert den Zustand der Liste
        items.add(title);
    }
}

Wenn jemand list() auch hundertmal aufruft – die Liste ändert sich nicht, und das entspricht der Erwartung an GET. Wenn jemand add(...) aufruft – die Liste ändert sich, und das entspricht der Erwartung an POST. Das scheint banal, aber genau auf solchen „Banalitäten“ baut die Vorhersagbarkeit einer API auf.

Und nun eine kleine „mentale Prüfung“ für die Zukunft. Stellen Sie sich vor, Sie möchten unbedingt einen „bequemen“ Endpoint der Art erstellen: GET /api/v1/reading-list/add?title=Clean%20Code. Aus menschlicher Sicht klingt das wie „nun, ich rufe einfach die URL im Browser auf, bequem“. Aus Sicht des HTTP-Vertrags ist das eine Katastrophe: Das Neuladen der Seite wird zu einer wiederholten Hinzufügung. Jedes Werkzeug, das GET als sicher betrachtet und es wiederholen (oder auf seltsame Weise cachen) kann, wird gegen Sie arbeiten. Daher ist „bequem“ hier eine Falle, kein Vorteil.

7. Safe ist nicht gleich erfolgreiche Antwort

Eine weitere häufige Falle ist die Erwartung, dass safe-Operationen „immer grün“ sein müssen. Also, wenn GET, dann muss 200 kommen, sonst „stimmt etwas mit dem Server nicht“. Aber HTTP ist ehrlicher: Lesen kann die Ressource nicht finden, Lesen kann falsch formatiert sein, Lesen kann aufgrund eines internen Fehlers fehlschlagen. Und das sind alles normale (wenn auch unangenehme) Situationen.

Wenn der Benutzer ein Buch mit der ID 999 anfordert, das nicht existiert, kann der Server 404 Not Found zurückgeben. Das macht die Operation nicht unsafe – es ist immer noch Lesen. Das Lesen hat nur keine Daten gefunden. Wenn der Benutzer in der id keine Zahl übergeben hat, kann man 400 Bad Request zurückgeben. Das betrifft wieder nicht die Sicherheit, sondern die Korrektheit der Anfrage. Und selbst 500 macht aus dem Lesen keine „Änderung“ – es sagt nur, dass der Server die Anfrage nicht verarbeiten konnte.

Auf Code-Ebene sieht „eine sichere Operation kann fehlschlagen“ so aus:

class SafeButNotAlwaysSuccessful {

    String getItemById(long id) {
        // Validierung der Eingabedaten: das ist keine Änderung der Ressource, aber die Anfrage kann ungültig sein
        if (id <= 0) {
            return "400 Bad Request";     // Anfrage ungültig
        }
        // Negatives Szenario „Ressource nicht gefunden“ – das ist immer noch Lesen
        if (id == 404) {
            return "404 Not Found";       // Ressource nicht gefunden (bedingt)
        }
        // Positives Szenario „Ressource gefunden“
        return "200 OK";                  // Ressource gefunden
    }
}

Das ist natürlich ein Spielzeugbeispiel, aber es hält einen wichtigen Gedanken fest: safe/unsafe handelt vom Effekt auf die Daten, während Status den Ergebnis der Verarbeitung betreffen.

Und hier taucht noch eine wichtige Sache auf: Ein Status existiert nur für eine Anfrage, die überhaupt eine Antwort erhalten hat. Beim Lesen bedeutet das Fehlen einer Antwort normalerweise, dass wir einfach kein Ergebnis erhalten haben. Bei einer ändernden Operation ist das Bild unangenehmer: Der Client weiß nicht, ob der Server nichts getan hat oder ob er die Daten geändert hat und die Antwort unterwegs verloren ging. Daher betrifft safe/unsafe nicht nur die schöne Semantik der Methode, sondern auch, wie schmerzhaft die Unsicherheit wird, wenn das Netzwerk sich schlecht verhält.

8. Typische Fehler im Umgang mit safe/unsafe

Dieses Thema sieht genau so lange einfach aus, bis Sie anfangen, echte Endpunkte zu entwerfen oder zu implementieren. Dann stellt sich plötzlich heraus, dass „Sicherheit von Operationen“ keine Theorie ist, sondern eine tägliche Disziplin: Jedes Mal, wenn Sie eine Methode auswählen oder einen „kleinen Nebeneffekt“ hinzufügen, stärken Sie entweder den Vertrag oder machen die zukünftige Fehlersuche interessanter (im schlechten Sinne). Im Folgenden sind die häufigsten Fehler, die Anfänger machen.

Fehler Nr. 1: GET für Operationen verwenden, die Daten ändern, „weil es so einfacher aus dem Browser aufzurufen ist“.
Eine solche Lösung sieht am Anfang bequem aus, verwandelt aber sehr schnell eine wiederholte Anfrage in eine „wiederholte Änderung“. Neuladen der Seite, Wiederholung nach einem Netzwerkfehler, versehentlicher Doppelklick – und die Daten sind nicht mehr dort, wo erwartet. In der Backend-Welt bedeutet „einfacher“ fast immer „teurer später“.

Fehler Nr. 2: Glauben, dass eine safe-Operation nur 200 OK zurückgeben darf.
Eine sichere Operation kann 404 zurückgeben, wenn die Ressource fehlt, 400, wenn die Anfrage ungültig ist, und 500, wenn der Server defekt ist. Safe bedeutet nicht Success. Wenn Sie anfangen zu denken „GET = immer 200“, werden Sie normale negative Szenarien falsch interpretieren.

Fehler Nr. 3: Sicherheit und Idempotenz verwechseln.
DELETE ist normalerweise idempotent, aber unsicher, weil es den Zustand ändert. PUT ist oft idempotent, aber ebenfalls unsicher. Und POST ist normalerweise unsicher und nicht idempotent. Wenn Sie diese Konzepte vermischen, werden Sie falsche Entscheidungen über wiederholte Anfragen und darüber treffen, welche Methode „verwendet werden darf“.

Fehler Nr. 4: „Harmlose“ geschäftliche Nebeneffekte in das Lesen einbauen.
Logs und Metriken sind das eine, aber die Änderung des Status, Aufrufzähler, automatische Datenreparatur und andere geschäftliche Änderungen sind etwas anderes. Wenn GET beginnt, den beobachtbaren Zustand der Ressource zu ändern, wird es für den Client schwieriger, das System zu verstehen, und die Infrastruktur rund um HTTP hört auf, Ihnen zu helfen, und beginnt zu stören.

Fehler Nr. 5: Eine unsichere Operation durch einen schönen Status als sicher tarnen.
Manchmal führt ein Entwickler eine unsafe-Operation aus, gibt aber 200 OK zurück und denkt, alles sei in Ordnung. Der Status ist für das Verarbeitungsergebnis zuständig, nicht für die Semantik der Operation. Wenn Sie den Zustand geändert haben – ist es unsafe, selbst wenn „alles erfolgreich verlief“. Dem Client ist Vorhersagbarkeit wichtig, nicht Kosmetik.

1
Aufgabe
Java Server, Level 9, Lektion 1
Gesperrt
Lesen der Warteschlangengröße ohne Nebeneffekt
Lesen der Warteschlangengröße ohne Nebeneffekt
1
Aufgabe
Java Server, Level 9, Lektion 1
Gesperrt
Audit der Operationssemantik
Audit der Operationssemantik
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION