Reputation: 1356
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.
PUT /userStores/store1
Creates an empty user store with id store1
, does nothing if it already exists
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.
GET /userStores/store1
Lists all users in the user store with id store1
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
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
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:
POST
method will create a resource and which is the best HTTP
method to use for the purposePUT
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:
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
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