REST API - How to handle optional parameter in PUT method ? what is difference in implementation with PATCH method - rest

I'm a little confused about put method with optional paramter.
suppose the mode is
Pet {
name
catagory
tag (optional)
}
when I want to create a Pet, I can use post method, the tag can be omitted.
when I want to update a Pet, the problem comes to me. According to the http spec, PUT method will update the entity by replaces the whole resource, which means I need to pass tag parameter. If I didn't pass tag, the default value will be empty, but it will cause the existing tag be override to empty.
For patch method, it will only update partial parameter no matter if it is optional. It's clear to understand.
I don't know if I misunderstand something, currently, in PUT method, I need to figure out what parameter is passed, and then update correspond field. But this seems the same with PATCH method.

An important thing to understand is that the HTTP specification describes the semantics (what do the different requests mean), but does not describe the implementation (how do you do it). That's deliberate - the specification basically says that your server should pretend to be a key/value store, but it doesn't restrict how you implement that.
PUT is roughly analogous to saving a file: "here is an array of bytes, save it using this key". In cases where your storage is a file system, then you just write the array of bytes to disk. If your storage is an in memory cache, then you just update your cached copy.
If your storage is some RDBMS database? Then you have some work to do, identifying which rows in your database need to be changed, and what commands need to be sent to the database to make that happen.
The point is that the client doesn't care -- as a server, you can change your underlying storage from RDBMS to document stores to files systems to whatever, and that's not any of the client's business.
in PUT method, I need to figure out what parameter is passed, and then update correspond field. But this seems the same with PATCH method.
Yes. In both cases, you need to figure out how to edit your resource in place.
PUT may feel a little bit easier, in that it is semantically equivalent to "delete the old version, then create a new version". You don't have to worry about merging the provided data to the state you already have stored.

Related

REST: Should PUT endpoint compare the GET response before updating?

I am developing a REST API in Spring boot and i am trying to understand the PUT action. Currently my PUT action takes the object id and checks if the object is present and then replaced the object with the new one. I have the following questions.
Should i compare the old object with the new one before saving the new one to know if the newobject is modified at all and return an approriate http response status if the object is unchanged ?
If i do want to compare, what is the best way to know if the object is really modified or not
Thanks.
No, you don't need to compare generally. PUT means you need to replace all the values with new ones, but if you need to keep the created by or created time properties you should get the record from db and update necessary values form previous record to new one.
If you need to compare two objects you need to override equal and hashCode method. then you can check a.equal(b) to check whether values are changed. Keep in mind if object contains datatime or random generation numbers avoid adding them inside equal method.
PATCH is where you need to get the current record from db and update relevant values.
You can decide between PUT or PATCH, not all protocol support PATCH.
When a client needs to replace an existing Resource entirely, they can
use PUT. When they’re doing a partial update, they can use HTTP PATCH.
if you are using PUT there you need to do all compare things and check for example:
Get Object from DB
check and update whatever is updated business object
then save.
to answer your question, object is modified is not required you to compare value from existing object and new object.
but if client side OK to send only updated properties then PATCH is better to use.
to know more and how you can implement, please blog
HTTP PUT vs HTTP PATCH in a REST API
REST: Should PUT endpoint compare the GET response before updating?
Neither REST nor HTTP put any particular constraints on the implementation - only the semantics are constrained. RFC 7231
HTTP does not define exactly how a PUT method affects the state of an origin server beyond what can be expressed by the intent of the user agent request and the semantics of the origin server response.... Generally speaking, all implementation details behind the resource interface are intentionally hidden by the server.
RFC 7232 might have a clue to what you are looking for
An origin server MUST NOT perform the requested method if a received If-Match condition evaluates to false; instead, the origin server MUST respond with either a) the 412 (Precondition Failed) status code or b) one of the 2xx (Successful) status codes if the origin server has verified that a state change is being requested and the final state is already reflected in the current state of the target resource (i.e., the change requested by the user agent has already succeeded, but the user agent might not be aware of it, perhaps because the prior response was lost or a compatible change was made by some other user agent).
So as far as the spec is concerned, you can pretend that you changed things, even though a no-op was equivalent to what the client asked for.
If i do want to compare, what is the best way to know if the object is really modified or not
Not enough information provided. That's going to depend on things like how the origin server stores resource state. If you are just dealing with raw documents, then comparing two long hash keys could be fine.

Should Odata(V4) actions be invoked only with POST?

Odata V4 Spec says that Actions MAY have observable side effects and should be invoked using HTTP POST. But we do have scenarios where we need to use actions which just modifies some status.
For example :
1.You might want to mark status of a document identified by a id as locked
Endpoint - .../Documents({id})/lock().
Since I am doing a partial update here, In my opinion PATCH is more suitable.2. You might want to offer two ways of deleting a document
a) Just Hide Endpoint - ...../Documents({id}) This is with HTTP DELETE (no disputes)
b) Delete PermanentlyEndpoint - ...../Documents({id})/permanentDelete() This as an ODATA action. In my opinion, HTTP Delete would be more appropriate here instead of HTTP POST.
What is the recommended way to do this from Odata standpoint? Any help here is much appreciated.
Below is the information from SPEC.
SPEC
11.5.4 Actions
Actions are operations exposed by an OData service that MAY have side effects when invoked. Actions MAY return data but MUST NOT be further composed with additional path segments.
11.5.4.1 Invoking an Action
To invoke an action bound to a resource, the client issues a POST request to an action URL. An action URL may be obtained from a previously returned entity representation or constructed by appending the namespace- or alias-qualified action name to a URL that identifies a resource whose type is the same as, or derives from, the type of the binding parameter of the action. The value for the binding parameter is the value of the resource identified by the URL prior to appending the action name, and any non-binding parameter values are passed in the request body according to the particular format.
Thanks in advance
--ksp
From an OData standpoint, you always have to invoke an action with a POST, with any other verb, it won't work.
Both of your examples are things that I personally don't think are well suited to an action as there are already ways to do these things with OData and they use the verbs that you are mentioning.Updating a property is supported with a PATCH and deleting an object is supported with a DELETE. You mention that you have two different types of delete operations, this is more difficult but you could use a custom header to distinguish between them.
An action tends to be something that doesn't fit into the normal CRUD operations so it isn't always clear which HTTP verb should be used for this.
In your examples, it does feel right to want to use DELETE and PATCH. However, the problem comes because we need to have a standard to follow, bear in mind that OData actions are all discoverable through the metadata so could be consumed by a client with no knowledge of what the actions actually do and in this case, we need to have something defined. Since we know that actions affect the server in some way, to me, it seems like POST is the least bad option that is consistent for all actions.
At the end of the day, as the author, your API is yours to command. Just as we shouldn't use properties in C# class design that cause side affects in other properties, that doesn't mean we cant, and it can be pretty common.
From an OData standpoint, PATCH is analogous to using property accessors and actions or POST is for accessing methods.
Making the decision between PATCH or POST to affect change is therefor the same design decision between using property mutators (making them writable) or forcing the caller to set their values through related methods.
You might want to mark status of a document identified by a id as locked
Endpoint - .../Documents({id})/lock().
Since I am doing a partial update here, In my opinion PATCH is more suitable.
If your resource has a property called Locked, and your current lock() Action only sets the Locked property to true, then you could simply use PATCH to update just that Locked field.
Some common reasons to use an Action specifically for a lock process:
You want to execute specific logic when lock() is called and you want to maintain this logic in it's own method, rather than having complex conditional logic inside your patch handler.
You don't want the reverse logic, unlock() to be available to everyone, when a resource is locked, presumably only the user who locked it can release the lock or other conditions need to be satisfied.
as with the first point, this sort of logic is generally easier to maintain in its own method, and therefore Action.
You want to use Security Attributes to restrict access to lock() to certain security groups, yet you want all users to have read access the the Locked state field.
When a resource is locked other fields are also set, like LockedBy and perhaps DateLocked.
While all of that logic could be managed in your single PATCH endpoint logic for the controller, I can't stress enough how this can easily make your solution unmanageable over time or as the complexity of your resource increases.
More importantly: the documented and accepted convention is that PATCH will NOT have side effects, and as such there is no need to execute a GET after a PATCH because the same change on the client has been accepted on the server. Conversely, because a POST MAY have side effects, it is reasonable for the client to expect to execute a GET to get all the related changes if the response from the POST does not contain the updated resource.
In the case of Delete vs PermanentlyDelete now things become personal / opinionated...
By convention, the expectation of DELETE is two fold:
After a delete the resource should no longer appear in collection query results from a GET
After a delete the resource should no longer appear in item requests via GET
From a server point of view, if my resource has a soft delete, that simply sets a flag, and a permanent delete that deletes the record from the underlying store, then by convention I would use an Action called Delete() for the soft delete, and the permanent delete should use the DELETE http verb.
The general reasoning for this is the same as for the discussion about locked().
However, if the intention of soft vs permanent delete is to intercept the client's standard delete workflow, such that the permanent delete concept is hidden or otherwise abstracted in a way that it is not part of the usual workflow (the user has to go somewhere different, like the recycle bin to view deleted records and restore or permanently delete), in that scenario, use the HTTP verb DELETE for soft delete, and make a specific, perhaps collection bound Action to accept the request for permanent delete
This action may have to be unbound, or bound to the collection depending on how you implement your filtering, if we have deleted record 'xyz' such the GET: ~/document('xyz') returns NOT-FOUND then we can't really expect POST: ~/document('xyz')/delete() to execute...

REST API Design - Resource relationships and Idempotency of a PUT request: What, exactly, is meant by a full resource representation?

I understand that for partial updates, an action must be taken that is not idempotent. To that end, a valid approach is to make a POST request to that resource.
I have a question though about related resources. For example imagine the following resources with their properties:
Accounts
Id
Name
Account #
Users (a collection)
Users
Id
Name
Now imagine I want to make a partial update to an Account - for example, to change the Account's name.
I could make the following request as a valid partial update:
POST /account/id/123
{
"name" : "My New Name"
}
My question is regarding a full PUT request which must be idempotent and must include a full representation of the resource.
Could I do the following as a valid idempotent request?
PUT /account/id/123
{
"name" : "My New Name",
"accountNumber" : "654-345-4323"
}
Is that considered a valid, idempotent action? I've included all the top level "Account" information, but I question it because I didn't post all the USERS that belong to the account as well.
In order to be a valid idempotent request, would I need to include all of it's sub resources as well in the PUT request?
An easier way to understand is to consider that the PUT method ignores the current state of the target resource, so a "full resource representation" means that it must have all data needed to replace the existent resource with a new one.
In your example, that could be a valid full representation for an account with no users.
It's fine for the server to assume default values when something is missing, but that should be documented properly as some users might confuse with a partial update.
If you want to design the PUT request as the full resource replacement, then this means that you need also to assign values to all the assignable (editable) properties of a resource, including the relations (links) of a resource. Otherwise, the properties which are not set are considered as being set to null.
For partial requests, you can use PATCH HTTP method. There is also a convention of PUT if your resource representation is simple enough to allow that, that you can use partial updates.
PATCH vs. PUT
Quoting:
PATCH vs. PUT
The HTTP RFC specifies that PUT must take a full new resource
representation as the request entity. This means that if for example
only certain attributes are provided, those should be remove (i.e. set
to null).
An additional method called PATCH has been proposed recently. The
semantics of this call are like PUT inthat it updates a resource, but
unlike PUT, it applies a delta rather than replacing the entire
resource. At the time of writing, PATCH was still a proposed standard
waiting final approval.
For simple resource representations, the difference is often not
important, and many APIs simply implement PUT as a synonym for PATCH.
This usually doesn’t give any problems because it is not very common
that you need to set an attribute to null, and if you need to, you can
always explicitly include it.
However for more complex representations, especially including lists,
it becomes very important to be able to express accurately the changes
you want to make. Therefore, it is my recommendation now to both
provide PATCH and PUT, and make PATCH do an relative update and have
PUT replace the entire resource.
It is important to realize that the request entity to PATCH is of a
different content-type that the entity that it is modifying. Instead
of being a full resource, it is a resource that describes
modifications to be made to a resource. For a JSON data model, which
is what this essay is advocating, I believe that there are two
sensible ways to define the patch format.
An informal approach where you accept a dict with a partial
representation of the object. Only attributes that are present are
updated. Attributes that are not present are left alone. This approach
is simple, but it has the drawback that if the resource has a complex
internal structure e.g. containing a big list of dicts, then that
entire list of dicts need to be given in the entity. Effectively PATCH
becomes similar to PUT again.
A more formal approach would be to
accept a list of modifications. Each modification can be a dict
specifying the JSON path of the node to modify, the modification
(‘add’, ‘remove’, ‘change’) and the new value.

What is the point of PUT when PATCH can effectively do the same thing

From my understanding, if completely following the HTTP spec, if you are doing a PUT command you need to pass in all the data for the resource (whether or not it changes) and when doing a PATCH command you need to only pass in the data that is changing. So if I had a resource in which I was going to change every value of it, the PUT and PATCH command would have the same request except for the HTTP verb being used.
From a backend prospective, I am finding it hard to come up with a viable reason to have different functionality for PUT and PATCH. The REST API I have been building right now supports both methods however they point to the same code and the code really just does a PATCH as it does not request all the data of the resource, just the changed data. I would like to have a really good reason to have to maintain a separate code path for PUT for all my resources as that adds a bit to code maintenance.
Is there any reason to really have different functionality for both PUT and PATCH when the code for PATCH can really do a PUT too (besides you should follow the spec as I don't find that a great reason on its own in this case)?
Is it considered bad practice or acceptable to have both PUT and PATCH accept only a list of changed data of the resource?
Even though both verbs seem quite similar, there are small, mostly semantic differences that should be considered when using one of the verbs.
PUT is idempotent, PATCH is not, which means that the side effects of a sequence of identical PUT-requests are the same as for a single request. This is not true for PATCH, even though it can be forced to be idempotent.
It is possible to use PATCH in a way where you need to know the server-side state of the resource first. This makes collisions more 'dangerous' than PUT-requests, because if you base the operation on a point/state that has already changed in the meantime, you might corrupt the resource. It's on the client's behalf to take care such cases. This is not necessary for simple operations like appending a list item (because the previous state doesn't matter).
Unlike PUT, a PATCH is not of the same entity as the resource it modifies. It only describes some sort of delta, but not a full representation of the resource. Therefore, it is not quite true when you say "...if I had a resource in which I was going to change every value of it, the PUT and PATCH command would have the same request except for the HTTP verb being used". This also means, that a PATCH must not necessarily be of a smaller document size than the whole resource data you would use with PUT.
"It is expected that different patch document formats will be
appropriate for different types of resources and that no single format
will be appropriate for all types of resources. Therefore, there is
no single default patch document format that implementations are
required to support. Servers MUST ensure that a received patch
document is appropriate for the type of [the requested] resource"
- RFC 5789
The comparison between PUT an PATCH is not quite trivial as it may seem, because you also should consider POST, since POST can also be used for partial modification.
Right now, PATCH is just a proposal and has not been completely/officially standardized yet.
So, as you can see, there are some differences between PUT and PATCH. Sometimes it can be important to be able to accurately describe the changes of a resource, so there sure are appropriate use-cases for PATCH. I think it's a good idea to provide both, but be aware that they're not really the same. Use PATCH for realative/partial updates and PUT to update the entire resource.
The difference between PUT and PATCH is that PUT asks the server to completely ignore the current state, while PATCH asks the server to consider the current state before applying the payload.
You think there are no differences because you're using PATCH to update with a partial representation, passing the data that is changing. That's not how it works. PATCH should use a diff format that makes explicit the current state you're applying the change to, and the resulting state.
For instance, in a JSON API you want to update the email parameter with a patch. The current email is myemail#example.com. You shouldn't just send:
{'email': 'mynewemail#example.com'}
You MUST send something like:
{'old_email': 'myemail#example.com', 'new_email': 'mynewemail#example.com'}
The format may be designed by your, or you may adopt an standardized diff format, depending on your needs. There's an RFC proposal for a standard JSON patch format to be used in these cases.
The use case for a PUT is when you need to completely replace something, ignoring completely whatever is in there, if anything. For instance, an user who is updating his profile. No matter what he does, you want to keep the latest version, ignoring whatever existed before.
The use case for a PATCH is when you need to update something, while considering the current state, and only if it still matches the state it had the last time you checked. For instance, you need to flag some user for being behind in his payments, but between the start of the job and the actual request, the user actually paid and his profile was already updated by another client of your API. If you flag his account as unpaid by sending a full representation with a PUT, you'll overwrite the data saying he has already paid. If you update with a PATCH, the request will be applied only if the user still has the unpaid state you've seen before.
To answer your last question, it's not acceptable to do partial updates with PUT. A PUT request is a complete replacement.

RESTful API design: should unchangable data in an update (PUT) be optional?

I'm in the middle of implementing a RESTful API, and I am unsure about the 'community accepted' behavior for the presence of data that can not change. For example, in my API there is a 'file' resource that when created contains a number of fields that can not be modified after creation, such as the file's binary data, and some metadata associated with it. Additionally, the 'file' can have a written description, and tags associated.
My question concerns doing an update to one of these 'file' resources. A GET of a specific 'file' will return all the metadata, description & tags associated with the file, plus the file's binary data. Should a PUT of a specific 'file' resource include the 'read only' fields? I realize that it can be coded either way: a) include the read only fields in the PUT data and then verify they match the original (or issue an error), or b) ignore the presence of the read only fields in the PUT data because they can't change, never issuing an error if they don't match or are missing because the logic ignores them.
Seems like it could go either way and be acceptable. The second method of ignoring the read only fields can be more compact, because the API client can skip sending that read only data if they want; which seems good for people who know what they are doing...
Personally, both ways are acceptable.... however, if I were you, I'll opt for option A (check read-only fields to ensure they are not changed, else throw an error). Depending on the scope of your project, you cannot assume what the consumers know about your Restful WS in depth because most of them don't read documentations or WADL, even if they are the experienced ones. :)
If you don't provide immediate feedback to the consumers that certain fields are read-only, they will have a false assumption that your web service will take care all the changes they have made without double checking, OR once they find out the "inconsistent" updates, they complain to others that your web service is buggy.
You can approach this in two different ways if the read-only field doesn't match the original values...
Don't process the request. Send a 409 Conflict code and specific error message.
Process the request, send a 200 OK and a message stating that changes made the read-only fields are ignored.
Unless the read-only data makes up a significant portion of the data (to the extreme that transmitting the read-only data has a noticeable impact on network traffic and response times), you should write the service to accept the read only fields in the PUT and check them for changes. It's just simpler to have the same data going in and out.
Look at it this way: You could make inclusion of the read only fields optional in the PUT, but you will still have to / should write the code in the service to check that any read only fields that were received contain the expected values. You have to write the read only checking either way.
Prohibiting the read-only fields in the PUT is a bad idea because it will require the clients to strip away fields they received from you in the GET. This requires that the client get more intimately involved with your data and semantics than they really need to be. The clients will consider this a headache, an unnecessary complication, and downright mean of you to add to their burden. Taking data received from your GET, modifying one field of interest, and sending it back to you with a PUT should be a brain-dead simple round-trip for the client. Don't complicate things when you don't have to.