12 Stimmen

HTTP-Status 412 (Vorbedingung fehlgeschlagen) und Datenbankversionierung

Ich implementiere einen RESTful Webdienst, der auf eine Datenbank zugreift. Die Entitäten in der Datenbank sind versioniert, um mehrere Aktualisierungen zu erkennen. Wenn der aktuelle Wert zum Beispiel {"name":"Bill", "comment":"tinker", "version":3} wenn ein Benutzer PUTs {"name":"Bill", "comment":"tailor", "version":3} ist die Anfrage erfolgreich (200 OK) und der neue Wert lautet {"name":"Bill", "comment":"tailor", "version":4} . Wenn ein zweiter Benutzer PUTs {"name":"Bill", "comment":"sailor", "version":3"} wird diese Anfrage fehlschlagen (409 Conflict), da die Versionsnummer nicht übereinstimmt.

Es gibt bereits nicht-RESTful-Schnittstellen, so dass das Design der Datenbanken nicht geändert werden kann. Die RESTful-Schnittstelle ruft eine bestehende Schnittstelle auf, die die Details der Versionsprüfung übernimmt.

Als Faustregel für RESTful-Webdienste gilt, dass man sich, wann immer möglich, an die Details von HTTP halten sollte. Wäre es in diesem Fall besser, eine bedingte Kopfzeile in der Anfrage zu verwenden und 412 Precondition Failed zurückzugeben, wenn die Version nicht übereinstimmt? Der geeignete Header scheint If-Match zu sein. Dieser Header nimmt ein ETag (Entity Tag) auf, das ein Hash der Darstellung des aktuellen Zustands der Ressource sein könnte.

Wenn ich das täte, wären die ETags nur zum Schein, denn die Version wäre immer noch die echte, für die ich teste.

Gibt es irgendeinen Grund, warum ich dies tun sollte, andere als "machen es mehr RESTful", was auch immer das bedeuten soll?

22voto

mogsie Punkte 3807

Es ist immer angebracht, die HTTP-Spezifikationen zu befolgen, wenn Sie HTTP verwenden, und der Grund dafür ist einfach, dass Menschen, die die Spezifikationen verstehen, die Möglichkeit haben, die korrekt funktionieren .

412 sollte nur verwendet werden, wenn eine Vorbedingung (z. B. If-Match) führte dazu, dass der Versionsabgleich fehlschlug, während 409 sollte verwendet werden, wenn das Unternehmen einen Konflikt verursachen würde (die HTTP-Spezifikation selbst spielt auf dieses Verhalten in der Definition von 409 ).

Daher erwartet ein Client, der keine ETags sendet, auch keine 412. Umgekehrt wird ein Client, der ETags sendet, nicht verstehen, dass es ETags sind, die eine 409 verursachen.

Ich würde bei einer Möglichkeit bleiben. Sie sagen, dass sich "das Datenbankschema nicht ändern kann", aber das hindert Sie nicht daran (direkt in der HTTP-Server-Schicht), die Version aus der Datenbankdarstellung zu extrahieren und sie in das ETag-Feld zu setzen, und dann auf dem Weg nach innen den If-Match-Header zu nehmen und ihn zurück in das Versionsfeld zu setzen.

Aber es ist nicht verboten, es vollständig im Körper der Entität selbst zu tun. Man muss nur das Konzept und seine Funktionsweise erklären, während man bei der ETag-Lösung einfach auf die HTTP-Spezifikation verweisen kann.

Bearbeiten: Und das Versionskennzeichen muss nicht unbedingt ein Hash der aktuellen Ressource sein; eine Version ist durchaus akzeptabel. ETag: "3" ist ein absolut gültiger ETag.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X