We have a Restful API. In the response of the PUT API, we update the updated timestamp column in the database with the current time and return its value as part "updated" timestamp field in the json response.
My question is if none of the fields in the entity are updated in the PUT call, should the updated timestamp be changed or not?
To elaborate, when performing the same PUT call multiple times, without change in the entity data, should the updated timestamp change?
Are there any best practices?
The HTTP spec specifies that a PUT request should receive a complete representation of the resource and either create it if it doesn't exist (and respond with status 201 Created and empty body), or completely replace it if it does exist (and respond with 200 OK or 204 No Content status and empty body). That's (almost) all. Most APIs of course ignore the "no body should be returned" part.
The "updated" timestamp should not be treated as part of the resource, but rather as metadata about the resource, and updating it should be considered a side-effect of the request, which is out of scope of the spec and so you can treat it however you think is appropriate for your use case.
In my opinion it should NOT be updated because these timestamps are usually used for caching purposes, and since the resource has not been changed there's no reason to invalidate any cache (also keep in mind that PUT requests are not cacheable at all according to the spec). Another use case for the timestamp would be to show final users when the resource last changed, and in that case it would make no sense to update the timestamp if nothing has changed, it would just confuse users.
As an example, Ruby on Rails does not update the updated_at timestamp if no attributes of the model changed.
I would say that update date should reflect what actually happened.
If you actually updated the record (e.g. performed real database UPDATE call), then change the timestamp.
If you didn't actually do anything (e.g. just compared values and did nothing), then do NOT change update date. It would save you plenty of time if requests you're considered identical were actually not.
Also, as mentioned above, returning updated timestamps is not fully semantically correct, better use headers (Last-Modified for instance).
Related
I am passing request object and path variables in my http PUT method to update a record.
Is it ok to pass additional data (such as timestamp) as query parameters which i want to save in the final record that has on additional field(say timestamp) as compared to request object ?
Is it ok to pass additional data (such as timestamp) as query parameters which i want to save in the final record that has on additional field(say timestamp) as compared to request object ?
Short answer: that probably doesn't mean what you think it does.
Is it OK to use query parameters in a PUT request? Absolutely. Query parameters are just another piece of the resource identifier.
/15f3221f-ee3b-4155-bc75-f80855a9187e/abc
/15f3221f-ee3b-4155-bc75-f80855a9187e?abc
Those are two different resource identifiers, and the machines won't assume that they identify the same resource, but all of the http methods that would apply to one would also apply to the other, and mean the same thing.
There's nothing magic about abc of course, you could use a timestamp there
/15f3221f-ee3b-4155-bc75-f80855a9187e?1970-01-01
Changing the timestamp changes the identifier; as far as general purpose components are concerned, these next two examples identify different resources
/15f3221f-ee3b-4155-bc75-f80855a9187e?1970-01-01
/15f3221f-ee3b-4155-bc75-f80855a9187e?1970-01-02
You might imagine them as two different pages of a desktop calendar. Modifying the list of appointments in your 1970-01-02 document shouldn't change your 1970-01-01 calendar at all.
Metadata about a representation would normally be embedded within the representation itself (think HEAD element in an HTML document) or in the HTTP Headers. As far as I can tell, we don't have a standardized header that matches the semantics you want.
All that said: the server has a LOT of freedom in how it interprets a request to update the representation of /15f3221f-ee3b-4155-bc75-f80855a9187e?1970-01-02. For instance, the updating of that resource might also update the representations of many other resources.
(Do keep in mind caching, though - there are only a limited number of ways we can advise a general purpose client that some cached representations have been invalidated by a request.)
I have an application that takes user's input personal details (name, dob, etc.) and looks for a match in the database. I am not creating a record, nor editing one.
Now normally I'd use GET, but GET doesn't allow me a body, and all the data that needs to be checked has to be sent up. I run a database query against all the user's inputs to find a match. If the database returns a match then one is found, otherwise it returns an empty array and no match is found.
So can you recommend the correct RESTful method (HTTP) that I might use for this?
Thanks
As the semantics of the payload of a POST operation are defined by the service itself, it should be used in any case where the other operations do not fit. POST is therefore not only used to create new resources but also to trigger certain calculations and stuff like that.
The general question however is, why do you need such a method? If you fear overwriting any changes done by an other client to the resource between you fetching the state of a resource and requesting an update, i.e., you should consider using conditional requests as defined in RFC 7232 where either an ETag hash is calculated for the current state or the Last-Modified value is taken and added to response header. A client could then send the request including the payload to check first including a If-Match or If-Unmodified-Since header requesting the server to apply an update only if the precondition holds. If it fails the server would tell you that with a 412 Precondition Failed error response.
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.
Need some guidance on best practices for building a RESTful API in node.js
Let's say I have a person record like so:
{
id: 1,
name: 'Jon',
age: 25,
recordVersion: 1
}
If I need to increment the recordVersion every time a value gets changed, would I still use a HTTP PUT to update this record? I've researched on how PUT should be idempotent and should contain the newly-updated representation of the original resource, so I am no sure of what to do.
I could increment the recordVersion property on the first PUT call and send an error on the second PUT call with the same versionNumber of 1 (because it would have incremented to 2 at that point), but does this follow RESTful API standards?
Representation != State
The resources sent over the wire are a representation of the state, not the actual state.
It's perfectly fine to remove the recordVersion and to update it behind the scenes - however if you do that, it would be best to remove it from the representation returned by a GET to that resource as well. To understand why: idempotency is all about what would happen if you applied the operation multiple times in a row (it isn't guaranteed if other operations happen in between...), and about observable side effects.
PUT the data without the version
the data is updated
version code incremented
if you did a GET you would get the data you had PUT (with no version)
PUT the same data again without the version
the data is updated
version code incremented
if you did a GET you would get the same data you had PUT (with no version)
Idempotent, because the resource representation has not changed as a result of calling PUT twice, even though the internal entity state has changed - no observable side effects.
See http://restcookbook.com/HTTP%20Methods/idempotency/ for a bit more detail.
Using version codes to detect conflicts
As you note, you could use inspect the version and throw an error if it has changed - and in fact this is very RESTful, and in my opinion the best way to approach PUT as it helps avoid (often inexplicable) concurrency errors. If you detect this case, it would be appropriate to return a 409 Conflict http status code.
How this would work is:
PUT the data with the version (v1)
the data is updated
version code incremented
if you did a GET you would get the data you had PUT with the new version (v2) (this is a side effect, but it's ok to have a side effect from the first time you do an operation).
PUT the same data again with version (v1)
conflict is detected because v1 != v2
409 Conflict returned
if you did a GET you would get the same as the result of the first operation - the data you originally PUT with the version v2
This is idempotent, because there have been no observable side effects as a result of calling the operation twice.
The client should, in response to a 409, do another GET to get the latest version code, and possibly offer to the user the opportunity to merge their changes with whatever else has changed in the meantime.
Often people confuse idempotency with thinking that the response to the operation must be the same as a result of multiple calls, but that is not the case - it is about there being no observable side effects as a result of multiple sequential calls.
I want to implement a "get changed values" capability in my API. For example, say I have the following REST API call:
GET /ws/school/7/student
This gets all the students in school #7. Unfortunately, this may be a lot. So, I want to modify the API to return only the student records that have been modified since a certain time. (The use case is that a nightly process runs from another system to pull all the students from my system to theirs.)
I see http://blog.mugunthkumar.com/articles/restful-api-server-doing-it-the-right-way-part-2/ recommends using the if-modified-since header and returning a representation as follows:
Search all the students updated since the time requested in the if-modified-since header
If there are any, return those students with a 200 OK
If there are no students returned from that query, return a 304 Not Modified
I understand what he wants to do, but this seems the wrong way to go about it. The definition of the If-Modified-Since header (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.24) says:
The If-Modified-Since request-header field is used with a method to make it conditional: if the requested variant has not been modified since the time specified in this field, an entity will not be returned from the server; instead, a 304 (not modified) response will be returned without any message-body.
This seems wrong to me. We would not be returning the representation or a 304 as indicated by the RFC, but some hybrid. It seems like client side code (or worse, a web cache between server and client) might misinterpret the meaning and replace the local cached value, when it should really just be updating it.
So, two questions:
Is this a correct use of the header?
If not (and I suspect not), what is the best practice? Query string parameter?
This is not the correct use of the header. The If-Modified-Since header is one which an HTTP client (browser or code) may optionally supply to the server when requesting a resource. If supplied the meaning is "I want resource X, but only if it's changed since time T." Its purpose is to allow client-side caching of resources.
The semantics of your proposed usage are "I want updates for collection X that happened since time T." It's a request for a subset of X. It does not seem like your motivation is to enable caching. Your client-side cached representation seemingly contains all of X, even though the typical request will only return you a small set of changes to X; that is, the response is not what you are directly caching, so the caching needs to happen in custom user logic client-side.
A query string parameter is a much more appropriate solution. Below {seq} would be something like a sequence number or timestamp.
GET /ws/schools/7/students/updates?since={seq}
Server-side I imagine you have a sequence of updates since the beginning of your system and a request of the above form would grab the first N updates that had a sequence value greater than {seq}. In this way, if a client ever got very far behind and needed to catch up, the results would be paged.