Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a RESTful POST method be implemented to be idempotent?

Tags:

rest

http

post

I am designing a RESTful API that is managing favorites. Each favorite resource can contain details of two items that are considered as part of the favorite.

 HTTP POST /favorites

 {  "item1" : "ball",
    "item1-ID" : "1",
    "item2" : "bat",
    "item2-ID" : "2"
 }

Please excuse the rudimentary JSON payload. The focus is however on the semantics of the POST

The above POST method creates a new favorite resource (that contains a ball (ID 1) and a bat (ID 2))

My question is with regard to the expected behavior when the same POST request is sent twice. The first request will create a favorite (as expected). What should happen when the second request is sent?

1) Signal an error with 409

2) Signal a success with 201

1) is not idempotent (as POST is), while 2) makes POST idempotent.

Which is the correct approach?

like image 707
Sirish Renukumar Avatar asked Oct 21 '15 01:10

Sirish Renukumar


1 Answers

You are thinking about this in the wrong way. If a POST creates a new resource then the resource should have a URL that identifies it (e.g., http://.../favorite/1). When the second POST with the same payload happens, is a new resource created? If so, then you have two separate resources with unique URLs. If you application does not create a new resource, then the second POST would return the same URL as the first one.

Edit

The POST section of RFC7231 does not prohibit it from being implemented in an idempotent manner. It does provide some guidance though:

  • If a POST creates a new resource, then it SHOULD send a 201 (Created) response containing a Location header identifying the created resource
  • If the result of a POST is equivalent to an existing resource, then the server MAY redirect the UA to the existing resource by returning a 303 (See Other) with the appropriate Location header

POST is not required to change the state of a resource. However, GET and HEAD are required to be idempotent. I'm not aware of any method that is required to change state on the server.

Personally, I implement resource creating POST methods as returning a 303 redirect to the canonical URL for the resource as a matter of practice. I wasn't aware of the RFC distinguishing status codes for resource creation and re-use responses. The benefit of this approach is that it removes the need to include the created resource in the POST response and the GET to the canonical URL will cache the response in any intermediate caches that may be present. It also allows for the implementation of intelligent clients that do not retrieve the response and use the canonical URL (from the Location header) instead.

In your case, I think that I would adopt the 303 approach provided that a favorite has a URL of it's own; 201 would be strange if it did not. If there is very good reason for distinguishing the creation and re-use cases in the response, then a 201 when the new resource is created and a 303 when it is reused is appropriate. What I would not do is to return a 409 unless your application requires you to deny the creation of a resource that already exists.

like image 175
D.Shawley Avatar answered Sep 22 '22 04:09

D.Shawley