it-swarm.com.de

Einfügen einer Ressourcen-ID in die Nutzdaten oder Ableiten von URI

Beim Entwerfen einer API sind wir auf die Frage gestoßen, ob eine PUT-Nutzlast die ID der zu aktualisierenden Ressource enthalten soll.

Dies ist, was wir derzeit haben:

PUT /users/123 Payload: {name: "Adrian"}

Unser Routencode extrahiert die ID aus dem URI und fährt mit der Aktualisierung fort.

Die ersten Benutzer unserer API fragen sich, warum wir keine ID in der Nutzlast zulassen:

PUT /users/123 Payload: {id: 123, name: "Adrian"}

Der Grund, warum wir dies nicht zugelassen haben, ist, dass die ID in der Nutzlast und im URI doppelt vorhanden ist.

Wenn wir noch etwas darüber nachdenken, koppeln wir die Ressource an die URI.

Wenn der URI nicht über die ID verfügt, muss die Nutzlast geändert werden:

PUT /no/id/here Payload: {name: "Adrian"} < What user???

Gibt es Gründe, dies nicht zu tun?

13
Adrian Lynch

Sie sollen die Uniform Ressource Kennung mit der Ressource koppeln.

Wenn REST mit HTTP implementiert ist, verwenden Sie GET, um den aktuellen Wert der Ressource abzurufen, und PUT, um einen neuen Wert festzulegen. Das GET verfügt nicht über eine Nutzlast, daher muss die Ressource identifiziert werden durch den URI. Und der PUT wird logisch mit demselben URI durchgeführt, und die Nutzdaten sollten genau so aussehen, wie Sie es vom nächsten GET erwarten.

Sie können POST für verschiedene URI verwenden, aber es wäre nur weniger sinnvoll, da es unnötig asymmetrisch zum GET wäre. POST für gemeinsame URI könnte nur machen Sinn für die Schaffung neuer Ressourcen (POST /users/new, Nutzlast: {name: "Adrian"}, Antwort {id: 345, name: "Adrian"}), aber das ist nicht idempotent und daher sollte vermieden werden wenn Sie nach REST streben¹. Stattdessen sollten Sie die ID mit einem Anruf reservieren und dann mit PUT die neue ID festlegen. Dies ist fehlertolerant, da bei einem Fehlschlagen der ersten Anforderung die ID-Reservierung möglicherweise eine Zeitüberschreitung aufweist und PUT idempotent ist. Oder verwenden Sie eine vom Client generierte UUID.


¹ Die Definition von REST sagt nichts über Idempotenz aus, daher kann ich nicht wirklich behaupten, dass es nicht REST ist, wenn Sie nicht idempotente Operationen haben ändert nichts an der Tatsache, dass das Festhalten an idempotenten Anforderungen die Zuverlässigkeit erhöht, ohne sie zu komplizieren, und wird daher empfohlen.

14
Jan Hudec

Wenn wir noch etwas darüber nachdenken, koppeln wir die Ressource an die URI.

Wenn der URI nicht über die ID verfügt, muss die Nutzlast geändert werden:

PUT/no/id/here Nutzlast: {Name: "Adrian"} <Welcher Benutzer ???

Gibt es Gründe, dies nicht zu tun?

Die Antwort auf diese Frage hängt davon ab, ob Sie dem Client erlauben möchten, die ID zu ändern.

Wenn der Client die ID über einen PUT ändern kann, ändert sich der URI für die Ressource, und Sie sollten jedes Mal, wenn eine Ressource auf den alten URI zugreift, einen 301 Moved Permanent bereitstellen.

So beginnen Sie beispielsweise mit einer Ressource bei

/users/123

und der Client legt Folgendes auf die Ressource

{id: 222, name: "Adrian"}

die Ressource wurde aktualisiert und ihre URI ist jetzt

/users/222

Das Feld Location in der PUT-Antwort sollte den neuen URI enthalten. Wenn Sie zu /users/123 gehen, sollten Sie eine Antwort 301 erhalten, wobei das Feld Location auf den neuen zeigt /users/222 Ressource.

In den meisten Fällen möchten Sie jedoch nicht, dass der Client die ID ändern kann, da dies ziemlich schnell ziemlich chaotisch werden kann. In diesem Fall kann nur der Server die ID ändern, und Sie sollten sie aus dem PUT-Text herauslassen, da der Client diesen Status nicht aktualisieren kann.

Wenn Sie eine Anforderung an einen anderen URI in derselben Ressource senden, z

/users/adian_lync

wenn diese Ressource nicht vorhanden ist, sollte der Server sie erstellen und dabei eine ID erstellen

2
Cormac Mulhall