leozilla
leozilla

Reputation: 1356

REST: Is PUT allowed to create nested resource

Consider the following API which should be RESTful

I want to create UserStores and Users within them There can be multiple UserStores and each of them can contain multiple Users.

  1. PUT /userStores/store1

Creates an empty user store with id store1, does nothing if it already exists

  1. PUT /userStores/store1 -content { "userName":"John", "more":"details" }

Creates a user in the user store with id store1, if the store does not exist, it will be created. If the store and the user already exist, the user details will be updated.

  1. GET /userStores/store1

Lists all users in the user store with id store1

  1. GET /userStores/store1/John

Gets the representation about the user with name John in the store with id store1


a) Do you consider this API RESTful? (Adheres to the REST principles)

b) In case 1 and 2, I decide based on the content of the PUT request if a user store should be created or a user. Whats your opinion on that?

c) About case 2, If both resources do not exist, is it ok the create the parent UserStore resource as well as the User resource with a single PUT operation?

Upvotes: 0

Views: 534

Answers (3)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57299

Do you consider this API RESTful? (Adheres to the REST principles)

No; your use of the PUT method is not consistent with HTTP's uniform interface.

The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.

A PUT should be a no-op only if the representation provided in the request matches the state of the resource on the server.

A successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being sent in a 200 (OK) response.

If you want a create that doesn't do anything if the resource already exists, then the correct spelling to use is a conditional PUT, probably using an If-None-Match header

PUT /userStores/store1 -content { "userName":"John", "more":"details" }

This probably doesn't do what you want, as the semantics of the message says to update the store such that John is in it and nobody else is.

If you are trying to add or update John without affecting any of the other users in the store, then PUT has the wrong semantics; you need either POST or PATCH.

I decide based on the content of the PUT request if a user store should be created or a user. Whats your opinion on that?

With PUT, the semantics always that you are updating the resource specified in the URI. What your server implementation needs to do to achieve that update is its own concern -- REST doesn't care if your store is one big document with a bunch of user details stored in it, or if it is instead a bunch of user records that all share a foreign key, or whatever. That's part of the point of the resource abstraction: clients are not coupled to the server's implementation.

If both resources do not exist, is it ok the create the parent UserStore resource as well as the User resource with a single PUT operation?

That's fine.

Upvotes: 1

N00b Pr0grammer
N00b Pr0grammer

Reputation: 4647

Putting REST to the best use of HTTP methods, it is always recommended to have POST for creating resources. There are two reasons for it:

  1. Every request to a POST method will create a resource and which is the best HTTP method to use for the purpose
  2. On the other hand, PUT is an idempotent request/response method. This would fail if you're application tries to create a resource which already exists in your system.

Hence by definition and also by practical usage - it is always recommended to go with POST for creating resources instead of PUT.

Further to this explanation answering your questions:

  1. By definition, it is not a RESTful API
  2. Yes, you could use
  3. Yes, you could use

But in my opinion, none of your cases can be called completely RESTful and your API's would require lot of maintenance in the basic logic itself!

Hope this answers your question well!

Upvotes: 0

Emanuele Ivaldi
Emanuele Ivaldi

Reputation: 1332

Well, I am expecting the store to be created or to override the one that already exists when using PUT, I'd rather use POST if you want nothing to happens when the store already exists, PUT should be idempotent, thus:

a) yes if PUT creates or overrides an already existing store

b) as above

c) yes but following what I said above

Upvotes: 0

Related Questions