I'll ask this question this way - what are the software engineering concerns for not implementing my REST API the "right" way?
What do you mean the "right" way? Well, allow me to explain my perception of the right way, then I'll tell you how I am doing it (also, assume I am talking about a JSON REST API).
The right way
Statelessness. This is the part I do get. The client maintains the state always 100% the time forevermore. It's not the server's job, it's the client's.
The expected actions and response for each verb:
- GET - Gets a resource specified in full entirety, only limited by either the authorization in the request or a query parameter. This assures no modification of any resource in the process.
- POST - Given an entire resource description (like a JSON object), creates a resource, then returns that resource, with any server side properties also created, such as dates or IDs.
- DELETE - Deletes a specified resource, giving only some sort of 200 OK as the response
- PUT - Given an entire object declaration as input, updates the resource at a specific location, updating all fields of the resource to each of the fields given in the input. To be clear, this expects the entire object to be passed in as input. The entire updated resource is returned, with all fields (according to the authorization or any other input flags).
- PATCH - Given only the fields wished to be modified for a resource, updates just the fields in a specified resource that are given as input. (This is where I am unclear): The entire resource is returned? (Or is it just the updated fields? Dunno. Don't care.)
- Resource paths. Given the relationship of the resources to each other, a resource path may look like one of:
- /parentresource/:id/childresource/:childId/subresource/:subresourceId (In this example, a subresource belongs to a childresource, which belongs to a parent resource).
The way I want to do it
The above is my understanding of how a REST API is supposed to work. Now let me list some of my variations to the above:
- PUT/PATCH - What is the point of passing in the entire resource for modification? I only use PUTs to modify resources, and I only pass in the fields I want to be updated. As a result, I have no need to use PATCH
Resource Paths - I use GUIDs in my application. As a result, they will be globally unique. Why do I need the full resource path, including the parent resources, if I can just uniquely refer to a subresource by itself? Like:
If I were to do it the "right" way, trying to reference the subresource would require a full path like:
Is all that necessary? Because now I have to have additional error handling if my path contains a :subresourceId that is not actually owned by a given :childId, and ditto for a :childId not owned by a parent :id. My server side is taking care of resource authorization. Can't I just reference the resource itself, rather than the full path?
The return response. Let's say, for example, that my data structure is a hierarchical tree, with no practical limits on tree depth. Resources lie at different levels down the tree, in a hierarchical fashion.
- The GET is obvious. If I get this entire tree, I expect the entire tree as a response, with resources contained within resources.
- If I POST to create a new resource, PUT to update, or DELETE to remove, I want to see the deltas in the tree, rather than just seeing the resource that I created/updated/deleted. I don't want to have to again call the GET of the parent tree after every POST, PUT, or DELETE, especially if there are little changes to the tree and I only want to see the deltas.
Hopefully my questions are clear.
If you were to see a REST implementation as I described it, would you gawk at it and tell me of your software engineering concerns? If so, what would they be?