Updating a resource through REST (PUT/POST) - rest

When updating a resource via REST, should one include in the body just the values to update, or the whole object (current values and values to update)?
If a User object looks like this
User (id, name, age, sex)
and I want to update only his name and age, should my request look like this:
PUT /users/1
{"name":"john","age":18}
or like this:
PUT /users/1
{"name":"john","age":18, "sex":"m"}
And what should that look like on the server side?
#RequestMapping(value = "/{userId}", method = PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> updateUser(#PathVariable final int userId, #RequestBody User u){
//fetch user by ID
user.setName(u.getName())
user.setAge(u.getAge())
user.setSex(u.getSex()) //this will be empty?
return new ResponseEntity<String>(gson.toJson(user), HttpStatus.OK);
}
Or alternatively I could find out which variables were not included in the request body and do something like this
if(u.getName()!=null){
user.setName(u.getName())
}
if(u.getAge()!=null){
user.setAge(u.getAge())
}
if(u.getSex()!=null){
user.setSex(u.getSex())
}
Is there a right/wrong way to achieve this, or is it a case of just doing what's easiest?

PUT requests must be idempotent and should provide as its payload a complete representation of the entity it is replacing. (https://www.rfc-editor.org/rfc/rfc7231#section-4.3.4)
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 partial JSON object PUT request would be a PATCH with Content-Type: application/merge-patch+json (https://www.rfc-editor.org/rfc/rfc7396)
Things to think about. You might have multiple clients updating an entity at the same time, using a PUT could end up overwriting changes other clients have made.
In that case you might want to set a pre-condition to check if the object was updated between the time that the requesting client fetched the entity, made changes and submitted the PUT/PATCH request. For example the pre-condition could be a last updated timestamp, hash (Etag) or a version number; Or you could use a "last write wins" approach which is common in eventually consistent systems. It all depends on your system and the situation.
On the server side, if you support partial updates then as you have provided in your example, you would identify the set of properties included in the request and only set the specific ones that were provided.

Related

REST API Design: Path variable vs request body on UPDATE (Best practices)

When creating an UPDATE endpoint to change a resource, the ID should be set in the path variable and also in the request body.
Before updating a resource, I check if the resource exists, and if not, I would respond with 404 Not Found.
Now I ask myself which of the two information I should use and if I should check if both values are the same.
For example:
PUT /users/42
// request body
{
"id": 42,
"username": "user42"
}
You should PUT only the properties you can change into the request body and omit read-only properties. So you should check the id in the URI, because it is the only one that should exist in the message.
It is convenient to accept the "id" field in the payload. But you have to be sure it is the same as the path parameter. I solve this problem by setting the id field to the value of the path parameter (be sure to explain that in the Swagger of the API). In pseudo-code :
idParam = request.getPathParam("id");
object = request.getPayload();
object.id = idParam;
So all these calls are equivalent :
PUT /users/42 + {"id":"42", ...}
PUT /users/42 + {"id":"41", ...}
PUT /users/42 + {"id":null, ...}
PUT /users/42 + {...}
Why do you need the id both in URL and in the body? because now you have to validate that they are both the same or ignore one in any case. If it is a requirement for some reason, than pick which one is the one that is definitive and ignore the other one. If you don't have to have this strange duplication, than I'd say pass it in the body only
If you take a closer look at how HTTP works you might notice that the URI used to send a request to is also used as key for caching results. Any non-safe operation performed on that URI, such as POST, PUT, PATCH, will lead to (intermediary) caches automatically invalidating any stored responses for that URI. As such, if you use an other URI than the actual resource URI you are actually bypassing that feature and risk getting served outdated state from caches. As caching is one of the few constraints REST has simply skipping all caching via certain directives isn't ideal in first place.
In regards to including the ID of the resource or domain entity in the URI and/or in the payload: A common mistake in designing so-called REST APIs is that the domain object is mapped in a 1:1 manner onto a resource. We had a customer once who went through a merger and in a result they ended up with the same products being addressed by multiple IDs. In order to reduce the data in their DB they at one point tried to consolidate their data and continue. But they had to support still the old URIs they exposed for their products. In the end they realized that exposing the product ID via the URI wasn't ideal in their situation as it lead to plenty of downstream changes that affected their customers. As such, a recommendation here is to use UUIDs that don't give the target resource any semantic meaning and don't ever change. If the product ID in the back changes it doesn't affect the exposed URI at all. Sure, you might need a further table/collection to map from the product to the actual resource URI but you in the end designed your system with the eventuality of change which it now is more likely to coop with.
I've read so many times that the product ID shouldn't be part of the resource as it is already present in the URI. First, the whole URI is a unique identifier of that resource and not only a part of it. Next as mentioned above, IMO the product ID shouldn't be part of the URI in first place but it should be part of the resources' state. After all, the product ID is part of the products properties and therefore should be included there accordingly. As such, the media type exposed should contain all the necessities that a client is able to identify the product ID off the payload. The media type the resource's state is exchange with should also provide means to include the ID if you want to perform an update. I.e. if you take HTML as example, here you get served a HTML form by the server which basically teaches you where to send the request to, which HTTP operation to use, which media-type to marshal the request with and the actual properties of the resource, including the ones you are not meant to change. HTML does this i.e. via hidden input fields. Other form-based media types, such as HAL forms, JsonForms or Ion, might provide other mechanisms though.
So, to sum my post up:
Don't map the product ID onto URIs. Use a mapping from product ID to UUIDs instead
Use form-based media-types that support clients in creating requests. These media types should allow to include unmodifiable properties, such as hidden input fields and the like

How to properly structure REST endpoints for PUT and POST

I have a REST service for managing users.
HTTP GET("/users") - get all users
HTTP GET("/users/{id}") - get data for specific user
When changing something about the user I'm not sure how structure the paths for PUT/PATCH.
Option 1:
HTTP PUT ("/users") and transfer the user data (id, first name, last name) in the request body
HTTP PATCH ("/users") and transfer the user's ID and PASSWORD in the request body
Option 2:
HTTP PUT ("/users/{id}") and transfer the user data (id, first name, last name) in the request body
HTTP PATCH ("/users/{id}") and transfer the user's ID and PASSWORD in the request body
Option 3:
HTTP PUT ("/users/{id}") and transfer the user data (id, first name, last name) in the request body
HTTP PATCH ("/users/{id}/password") and transfer the user's ID and PASSWORD in the request body
#RequestMapping(value = "/users")
public interface UserController {
#GetMapping(value = "/{id}", produces = "application/json")
User getUser(#PathVariable long id);
#PutMapping(value = "", consumes = "application/json")
void addNewUser(#RequestBody User ser);
#PatchMapping(value = "/{id}/password", consumes = "application/json")
void changeUserPassword(#RequestBody UserPasswordChange passwordChangeModel, #PathVariable String id);
I'm not sure which of these approaches is the best. I can get all the data from the request body every time but I'm not sure what should be the best path to create. Using "/users/{id}" to change details about the user makes sense because I'm changing for a specific user but since I can read the ID from the request body, the path variable is redundant here.
It's the same confusion when changing the password. Since I have just one Patch endpoint under "/users" should I still use the "/users/{id}/password" or maybe I should delete the "/password" part?
When changing something about the user I'm not sure how structure the paths for PUT/PATCH.
Both PUT and PATCH are document editing requests. "Please make your representation of this resource look like mine".
In an idealized form, I would have some sort of HTTP aware document editor. I would GET a representation of the resource from you, make edits to my local copy, then send a representation of my local copy back to you.
Getting useful work done is a side effect of passing these documents around. See Jim Webber's talk.
Options 1, I think we can simply reject on first principles. If the resource identified by /users is a collection of users, then trying to replace its representation with that of a single user is not a step in a useful direction. Semantically, if you wanted to edit or insert a user by interacting with the /users resource, you would do that by either (a) making an edit to the representation of the collection, and sending the entire representation back (PUT), or by sending a description of the diff back to the server (PATCH).
Option 2, has a subtler issue -- if the password is part of the representation of the /users/id resource, then the password should also be part of the body of the PUT request. PUT and PATCH are different ways of passing our local representation of the resource back to the server; we shouldn't be thinking of them as having different information about the resource.
It's perfectly reasonable to separate the password into a different resource from the rest of the user. Unless the representation of the password resource is very large relative to the password itself, I would expect PUT rather than PATCH to be used in most cases.
So you are suggesting that option 3 would make the most sense?
Not quite - both resource designs (either with all of the information available in one resource, or with the information divided between two resources) are fine. You pick one, and then make sure the idioms you use for updating the resource(s) are appropriate.

Embedding collections (subdocument arrays) with MongoDB violates REST?

Let's say I have a users collection in my Mongo database:
users
_id
emailAddress
firstName
lastName
passwordHash
accessLogs: [ ... ]
createdAt
As you can see, a user document can contain an array of accessLogs. Great.
But let's say I want to update a user record and do a PUT /users/:id request against my RESTful API that uses this database. With a PUT, you're supposed to get back what you put in. So let's say the user has logged in 500 times. In order to avoid violating REST, does this mean my PUT data should include the accessLogs array and all its items?
I suppose the request handler could just update everything except accessLogs.
In the strictest definition PUT should indeed replace the contents of the object. If you want to update an existing object with partial data/instructions instead, you should use the PATCH method. This would allow you to specify that you want to add accessLogs (or otherwise leave them unmodified) and not have to send the entire object -- just instructions for what needs to be updated.
In your case the accessLogs is a generated read-only property and so it does not have to be part of your PUT request. You don't send the _id property as well and if some of the properties have default values, you don't have to send those either.
The PUT method requests that the enclosed entity be stored under the
supplied Request-URI. If the Request-URI refers to an already existing
resource, the enclosed entity SHOULD be considered as a modified
version of the one residing on the origin server.
Hypertext Transfer Protocol - HTTP/1.1
The difference between the PUT and PATCH requests is reflected in the
way the server processes the enclosed entity to modify the resource
identified by the Request-URI. In a PUT request, the enclosed entity
is considered to be a modified version of the resource stored on the
origin server, and the client is requesting that the stored version be
replaced. With PATCH, however, the enclosed entity contains a set of
instructions describing how a resource currently residing on the
origin server should be modified to produce a new version. The PATCH
method affects the resource identified by the Request-URI, and it also
MAY have side effects on other resources; i.e., new resources may be
created, or existing ones modified, by the application of a PATCH.
PATCH Method for HTTP
You can find a similar question here.

Is it a bad practice to return an object in a POST via Web Api?

I'm using Web Api and have a scenario where clients are sending a heartbeat notification every n seconds. There is a heartbeat object which is sent in a POST rather than a PUT, because as I see it they are creating a new heartbeat rather than updating an existing heartbeat.
Additionally, the clients have a requirement that calls for them to retrieve all of the other currently online clients and the number of unread messages that individual client has. It seems to me that I have two options:
Perform the POST followed by a GET, which to me seems cleaner from a pure REST standpoint. I am doing a creation and a retrieval and I think the SOLID principles would prefer to split them accordingly. However, this approach means two round trips.
Have the POST return an object which contains the same information that the GET would otherwise have done. This consolidates everything into a single request, but I'm concerned that this approach would be considered ill-advised. It's not a pure POST.
Option #2 stubbed out looks like this:
public HeartbeatEcho Post(Heartbeat heartbeat)
{
}
HeartbeatEcho is a class which contains properties for the other online clients and the number of unread messages.
Web Api certainly supports option #2, but just because I can do something doesn't mean I should. Is option #2 an abomination, premature optimization, or pragmatism?
The option 2 is not an abomination at all. A POST request creates a new resource, but it's quite common that the resource itself is returned to the caller. For example, if your resources are items in a database (e.g., a Person), the POST request would send the required members for the INSERT operation (e.g., name, age, address), and the response would contain a Person object which in addition to the parameters passed as input it would also have an identifier (the DB primary key) which can be used to uniquely identify the object.
Notice that it's also perfectly valid for the POST request only return the id of the newly created resource, but that's a choice you have, depending on the requirements of the client.
public HttpResponseMessage Post(Person p)
{
var id = InsertPersonInDBAndReturnId(p);
p.Id = id;
var result = this.Request.CreateResponse(HttpStatusCode.Created, p);
result.Headers.Location = new Uri("the location for the newly created resource");
return result;
}
Whichever way solves your business problem will work. You're correct POST for new record vs PUT for update to existing record.
SUGGESTION:
One thing you may want to consider is adding Redis to your stack and the apps can post very fast, then you could use the Pub/Sub functionality for the echo part or Blpop (blocking until record matches criteria). It's super fast and may help you scale and perfectly designed for what you are trying to do.
See: http://redis.io/topics/pubsub/
See: http://redis.io/commands/blpop
I've used both Redis for similar, but also RabbitMQ and with RabbitMQ we added socket.io connection to "stream" the heartbeat in real time without need for long polling.

Make a RESTful API call that updates many related entities

We have a model that looks like this
Login <- Email Addresses <- Person -> Teen
And a stored procedure which takes some properties from teen, some from person, and some from Login, and creates a new teen, returning a person entity.
Looking from a classic RPC perspective, this is easy...just expose a method InsertTeen and have it call the stored procedure.
I've been trying to wrap my head around the RESTful idea of having URLs as my resources (nouns), and the only actions being HTTP actions (verbs). Obviously, a URL like /api/InsertTeen is not RESTful at all.
But here I'm not dealing with any particular resource.
The only thing I can thing of here would be to expose a resource like insertTeenRequest.
Are there any other ideas of how to do this? Am I being too much of a "zealot"?
If you want to be really RESTful, you should use several requests to your API in this case. For example first you create Teen with POST to /api/teens/, then create Person with POST to /api/persons/ and so on.
Pretty new to REST myself, but my thinking is that here you would use a "POST" with the body of the request containing the data needed to create a 'Teen', in whatever format you are using, usually JSON or XML. Here, I'm not sure whether you treat Teens as Persons with additional properties, or a Teen is modeled as an entity itself:
<person login="abc" email="abc#foo.com">
<person-property-1>value1</person-property-1>
<person-property-2>value2</person-property-2>
<teen>
<teen-property-1>value3</teen-property-1>
<teen-property-2>value4</teen-property-2>
</teen>
</person>
or
<teen login="abc" email="abc#foo.com">
<person-property-1>value1</person-property-1>
<person-property-2>value2</person-property-2>
<teen-property-1>value3</teen-property-1>
<teen-property-2>value4</teen-property-2>
</teen>
Regarding the URI, I believe the segments should be nouns rather than verbs since the URI is supposed to address a resource, so /api/teens rather than /api/InsertTeen.
/api/teens with an HTTP GET would return a list of all Teens, and /api/teens with an HTTP POST would insert a new Teen. To round out the CRUD operations, /api/teens/{id} using HTTP GET would return a specific Teen, /api/teens/{id} with an HTTP PUT would update a Teen using the values passed in the request body, and /api/teens/{id} called with HTTP DELETE would delete the specified Teen.
Edit
Read over your question again, and I may have misunderstood. If you aren't treating 'teens' as a resource, but only 'people', then I would consider /api/people with an HTTP POST, and depending on the values passed in the body of the request, do whatever is appropriate to store that 'person'. So, if the request contained 'teen' values, call your stored procedure that creates a 'Teen' and returns a 'Person'.
HTH