Greg Beech
Greg Beech

Reputation: 136637

Responding to an idempotent HTTP POST request

Part of our RESTful API will allow users to register an item with a serial number. As the serial number is not globally unique it cannot be used as the identifier of the resource, so we'll use a POST to the parent resource which will generate an identifier, e.g.

POST /my/items

<item serial-number="ABCDEF" />

In the case where the item is not already registered, the HTTP semantics are well defined. We return a Location header, and the registered item as the entity body, e.g.

HTTP 201 Created
Location: /my/items/1234    

<item id="1234" serial-number="ABCDEF" />

However, in the case where the item is already registered, the API should be idempotent and return the previously registered item without creating a new one. My best guess is that it should then return a 200 OK status code, and use the Content-Location header to indicate where the item actually came from, e.g.

HTTP 200 OK
Content-Location: /my/items/1234    

<item id="1234" serial-number="ABCDEF" />

Would this seem reasonable? I'm not entirely clear whether the Location or Content-Location is more suitable in the second case.

Upvotes: 6

Views: 1904

Answers (2)

manuel aldana
manuel aldana

Reputation: 16438

I had similar requirement recently. For idempotent operations PUT is the best way. You're right there is a mismatch between the external-id and the internal one. I solved it by creating a dedicated resource for the external id target:

PUT /api-user/{username}/items/{serialNumber}

Internally I resolve it as a CREATE in case I have no item for 'username' and 'ABCDEF' serial number or UPDATE in case I do.

In case it was a CREATE I return 201 for an UPDATE 200. Further more the returned payload contains both homegrown id and the external serial number like you suggested in your payload.

Upvotes: 7

Darrel Miller
Darrel Miller

Reputation: 142094

Here is an interesting discussion on usages of the two headers. It claims Content-Location is not defined for PUT or POST so Location is possibly the better option in your case. It is certainly not clear cut which is better though.

Overall I think your approach makes sense though.

Upvotes: 1

Related Questions