Roni Axelrad
Roni Axelrad

Reputation: 439

does unique keys break the POST non-idempotency?

I read a lot about idempotent and non-idempotent and I think that I understand the concept clearly. However, a though of a scenario of a POST is confusing me.

a POST should always create a new resource. for example:

  1. POST api/persons { Name: "John" } --> persons/1
  2. POST api/persons { Name: "Jack" } --> persons/2
  3. POST api/persons { Name: "Jack" } --> persons/3

now that's obvious, but let's say a person has an ID as the PK, but also SSN which is a unique key. In that case, If I send two POST requests with the same SSN, it would not create two new resource:

  1. POST api/persons { Name: "John", SSN: 123 } --> persons/1
  2. POST api/persons { Name: "Jack", SSN: 123 } --> error

Note that I didn't send the ID PK, therefore in theory, the POST should consider it a new resource and create it.

Does that breaks the REST POST non-idempotency standart ?

Upvotes: 0

Views: 328

Answers (1)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57297

POST should always create a new resource.

That's a misconception - you can use POST for other purposes. It's deliberately very generic.

Does that breaks the REST POST non-idempotency standard?

No, because POST isn't required to be non-idempotent.

For example, suppose we want to provide a web API that allows the consumer to query information in a database. Since the operation is "essentially read only", we can use messages with safe semantics.

That we would normally do by using a GET, and using the query string to describe the parameters of the query.

But there are defacto limits to the length of a URI, and therefore limits on the length of a query. If we need to support queries that exceed those limits, our only option is to move the parameters into the request body.

And the standard "safe" HTTP methods don't have well defined semantics for the request body.

So to ensure correct behavior, we use POST, rather than GET. The effect at the server is still "essentially read only", but generic components that can only see the messages (and not our out of band API documentation), will not know that the message is safe, and will not be able to perform optimizations (caching, automatic resend, crawling) that would be available when safe methods are used.

Put another way, everything we do in HTTP could be done with POST - what the other methods do is allow us to unlock optimizations in generic consumers/observers of the messages.

In practice, HTTP doesn't constrain the implementation at all -- it describes semantics. Here's Roy Fielding explaining in 2002:

HTTP does not attempt to require the results of a GET to be safe. What it does is require that the semantics of the operation be safe, and therefore it is a fault of the implementation, not the interface or the user of that interface, if anything happens as a result that causes loss of property (money, BTW, is considered property for the sake of this definition).

POST doesn't promise to be idempotent, and therefore clients are broken if they assume that it does make that promise.

Upvotes: 1

Related Questions