Reputation: 16969
As other people (for example: here) I'm struggling with the question, if the representation for GET and PUT should be the same?
Example:
GET representation:
{
"id": "0815",
"name": "jdoe",
"emailAddress": "[email protected]",
"displayName": "John Doe",
"active": true
}
PUT representation:
{
"emailAddress": "[email protected]",
"displayName": "John Doe"
}
Research:
I read in REST question: PUT one representation, GET a different one? that it is ok, to get another media type with GET as I saved with PUT.
I read in REST - put IDs in body or not? that it is ok, to omit the id with PUT and get the id with GET.
I read in GET Representation != POST Representation that it is ok, to omit a lot of properties with PUT and get them with GET. An example is JIRA REST API - api/2/myself. GET returns the hole user model and PUT saves only 3 properties.
Is that good practice? I could also use PATCH, for example GitHub REST API - users. What's the reason to add PATCH to HTTP, if PUT with another smaller representation is already enough?
Further more I read in Best practice for partial updates in a RESTful service that most big REST APIs (for example: Google) use PATCH or POST for partial updates and PUT only for complete/full updates (for example: Goolge - Updating an entity).
Upvotes: 8
Views: 2312
Reputation: 13110
I struggled with this exact same question. Thanks for your research into it and for articulating it well. I think the issue here is that there is data that has to be determined/created by the server/backend that REST hasn't really addressed a best practice for. For example:
In every trivial REST example you see it appears to be pretty symmetrical between what you GET vs what you POST/PUT. For example, REST would lead you to believe that if you do a GET on a collection (or resource) and then POST (or PUT) that response body back that there should be no change, but that's just not realistic considering the aforementioned examples. So in essence your GET response becomes a superset of the actual POST/PUT body.
The terminology I've used for this as a head nod to the relational asymmetry between the two has been to say that my GET returns a Readonly representation of the collection/resource, versus that the POST/PUT body accepts. That lends itself nicely to code where you can inherit a Readonly
representation from the object to augment it with the properties that your server/backend is responsible for creating/managing. For example, here's two TypeScript interfaces showing what data a user could PUT (IPet
) versus what data the server would respond with for a GET (IReadonlyPet
)
interface IPet {
name: string, // The user can change the pet's name
}
interface IReadonlyPet extends IPet {
id: number, // The user should not be able to change the pet's id
}
I don't know if I'd force a user to strip off things like id
when making a POST/PUT subsequent to a GET request as that's a lot of data transformation work to ask of your API consumers. I can see two valid and opposing arguments:
id
than they received and you're just silently ignoring it could potentially give them a false sense of the actual state of the collection/resource)id
, then do a POST/PUT and you would simply ignore the id
property.If I had to choose one, I'd probably go with the second option because I think it makes for a simpler, more symmetrical experience for your API consumers in that they can do a full circle GET, POST/PUT the GET response, and GET again to receive the same original response. Additionally, your API consumers can't really complain about implementation behavior for data that goes beyond the defined schema since you're already off the beaten path of standardization.
Upvotes: 5
Reputation: 6392
The idea is that the server generally has more information about the resource than the user, and so GET might return more information than is required for PUT. There are some things which the server 'owns', and so cannot be updated by the client. These can be returned by GET while the PUT representation does not allow the user to modify them.
However, that's not the same thing as saying that PUT allows you to partially update the resource. When you PUT a document you update all of the values which that document covers - so an 'optional' value which is not present in the actual document sent via PUT should be removed from the resource. When you do a subsequent GET on that resource, the optional value will not be present.
The semantics of PATCH are supposed to be slightly different - with PATCH the client sends a partial update which describes changes in some way. Those changes are then applied to the resource in some fashion. Parts of the resource which are not mentioned in the document sent via PATCH will be unmodified.
Also, note that PATCH is explicitly defined as neither safe nor idempotent. Whereas PUT is idempotent but not safe - the same request repeated will result in the same change. With a PATCH, some changes could be cumulative (e.g. add a value to a list) and so duplicated requests could result in a different state of the resource.
Upvotes: 6