Is it possible to make the same field compulsory for POST and optional for PUT requests? - rest

Is it possible to make the same field compulsory for POST and optional for PUT requests for REST API? Or it depends on teqnology used to implement this request?
For example, there is a POST request to create Car objects and this object has a field model_id which is actually chosen from a dictionary of models. And the POST request requires model_id because the car must have model_id defined.
And I want to have a PUT method which changes some field e.g. serial_num, manufacture_date, color etc. even model_id. But I want this PUT method to change model_id as optional parameter, e.g. I just want to change color and it is Ok.
So is this possible in REST? Does some technologies that implement these request could not allow me to make different set of optional/compulsory params for POST ant PUT?

Well, you can do whatever you want here. Nobody will kill you if you check fields in the request body and return an error if model_id is specified (or not).
Some guys use POST method to update entities in API.
If you want to be closer to standards better use PATCH for partial updates.
You can find a lot of interesting info here:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
Use of PUT vs PATCH methods in REST API real life scenarios
https://www.rfc-editor.org/rfc/rfc7231#section-4.3.4
https://www.rfc-editor.org/rfc/rfc5789
One important thing from 4. source:
The PUT method is already defined to overwrite a resource with a
complete new body, and cannot be reused to do partial changes.
And another one sentence from 3. source:
Generally speaking, all implementation details behind the resource interface are intentionally hidden by the server.

Related

REST - Does the PUT method have to remove an optional field when it is omitted?

I have a resource Car which have some required fields and another optional ones.
The Car was created with the following request:
POST /cars
{
plate: "XYZ-A2C4",
color: "blue,
owner: "John" //OPTIONAL
}
A REST client wants to update all required info of this car:
PUT /cars/:id
{
plate: "ABC-1234",
color: "black"
}
What happen to the owner optional field?
It will be removed, since it was not informed? ie: PUT must replace the entire resource with the representation passed in the payload ?
Or, since owner is not required, the server may preserve the old value?
I know that the server can provide a PATCH method, but sometimes it is not possible to update a single field because the new state could become invalid (there are no minimum required payload to enforce related fields values). Also, manipulating arrays, removing fields or setting it with null can be tricky in some cases with PATCH since it can be done with two different patterns; JSON Merge Patch is limited and JSON Patch is kinda strange.
Is it OK to perform a PUT with the required fields and the server preserves the old optional values when it is omitted?
If you want to go by the book (being section 4.3.4 of RFC 7231), then yes, the PUT request should, in your case, replace the entire Car resource:
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 successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being sent in a 200 (OK) response.
So, by the book, you should not use PUT for partial updates, but rather PATCH.
However, in practice, it is really up to you to decide how exactly this is applicable to your service, and more importantly, to document it.
Here are a few real-world examples of how some well-known APIs allow partial updates:
The Ghost API does not support partial resource update, it requires a PUT request with a full resource for any update
The Rossum API supports PATCH for partial resource update, but their documentation explicitly states that only top-level properties are supported
GitHub allows both PATCH and POST requests for partial data updates
Firebase allows PATCH requests but also POST with an X-HTTP-Method-Override header
You are exactly right that sometimes, a PATCH method could result in an invalid resource if processes as-is. However nothing prevents the server from ensuring proper data state as a side-effect. Therefore, during each call you can have the server:
verify the proper state of the resource before persisting it
reject (with a 400 Bad Request error) any request that would result in improper state
respond with the resource (maybe bearing side-effects) on success
Strictly speaking PUT should replace the resource being identified with the entity that is being supplied. In your example, that would mean car would be replaced without the optional field unless the optional field was also supplied in the PUT request.
The number of APIs that strictly adhere to REST or a resource oriented architecture are pretty few and far between, so I personally would try not to sweat this level of detail and just document your api and the behavior that your users can expect.
If you really want to be fanatical about it, I think you're on the right track with PATCH, or you could identify a sub-resource:
PUT /cars/:id/plate
"ABC-1234"
PUT /cars/:id/color
"black
OR perhaps:
PUT /cars/:id/description
{
plate: "ABC-1234",
color: "black"
}
The www-tag mailing list archives include this interesting observation from Roy Fielding in 2002:
HTTP does not attempt to require the results of a GET to be safe. What it does is require that the semantics of the operation be safe, and therefore it is a fault of the implementation, not the interface or the user of that interface, if anything happens as a result that causes loss of property (money, BTW, is considered property for the sake of this definition).
The specification for HTTP PUT should be understood the same way; the specification tells us what the messages mean, but not how to do it.
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.
PUT semantics are fundamentally "remote authoring"; the request tells the server to make its copy of a resource look like a clients copy.
So when you leave an "optional" element out of the representation provided in the request, you are telling the server to remove that optional element from its own representation as well.
It's the responsibility of the client to create a message that describes what the actually wants. So if you the client intend that the optional fields are unchanged after your request, you need to include them in the representation that you include in the body of the request.
The server is expected to interpret the PUT request as described; but it is not constrained in what it does with such a thing (subject to Fielding's observation above: which way does the blame finger point when things go wrong?)
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.
What happen to the owner optional field?
So in your specific example, the request clearly says "do not include the owner element". But the server is allowed to ignore that; it need only be careful in crafting its response not to imply that the provided representation was stored unchanged.

Moving child resource to another parent in REST

I have a REST service.
And now I need to have functionality to move some child resources from one parent to another, for example move a book from one author to another.
My variant is:
POST /api/books/x/moveto/y
But how to create such architect the RESTful way?
From a REST point of view, URLs should be used to locate the resources rather than expressing operations. To express operations, the existing HTTP verbs should be used.
Looks like your "move" operation is all about replacing the author of the book.
And the PUT method seems to be the way to go:
4.3.4. PUT
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. [...]
So, you can have an endpoint like the following:
PUT /api/books/{bookId}/author
And the request payload will contain a representation of the new author.
I think in this case updating the author as suggested in Cassio's answer is a good solution. For less obvious "actions" I use PATCH endpoints. Consider archiving a book:
PATCH /api/books/{bookId}/archive
The intent is obvious -- archive the book with this identifier. For more complex actions, include a body or use a query string parameter. For instance, moving a book out of one category and into another (assume a book can have 0-many categories):
PATCH /api/books/{bookId}/move
{
fromCategoryId: 100,
toCategoryId: 200
}
Or:
PATCH /api/books/{bookId}/move?fromCategoryId=100&toCategoryId=200
In the end, IMO, what matters most is readability and consistency. There is not necessarily a "right" way to do this sort of thing.

What REST action should I use for Validate?

I have a design question on REST. I need to expose a validate method as a rest resource. Let us say it looks like this
public ValidatedResult validate(ObjectToBeValidated object)
ObjectToBeValidated is a class that contains the actual Object and also some parameters concerning the validation.
When I design this as a Restful resource, which action do I use? From my understanding GET is the action that best suits this case. If that is so, how I can pass my ObjectTobeValidated as an object but not as URL parameters? I shy away from URL parameters because ObjectToBeValidated may contain a lot of properties, ending up with an URL like below which is feel is too long
http://localhost/rest/validate?prop1=somevalu&prop2=somevalue&prop3=something&prop11=somevalu&prop22=somevalue&prop33=something
Any help would be appreciated
Thanks
Kay
The HTTP standard allows you to use the POST method. It does not necessary need to have a side effect.
The action performed by the POST method might not result in a resource
that can be identified by a URI. In this case, either 200 (OK) or 204
(No Content) is the appropriate response status, depending on whether
or not the response includes an entity that describes the result.
HTTP 1.1 / method definitions / POST
In your case you can do something like this if you want to follow the noun-verb approach Tim suggested:
POST /api/my/object/validator
Be aware that by REST the messages must be self-descriptive, so either you need a vendor MIME type or you need to add meta-data e.g. RDF to describe what this link does and what params are allowed. Otherwise we are not talking about REST, just a regular webapp.

REST - Common practice for "change-all" mutations

In my app there is a button which (when clicked) should apply some mutation to all entities (of a certain type). Assuming my entities are "purchases" clicking on the "confirm all" button should result in the server/db setting the "confirmed" field of all "purchases" to "true".
I have the code that does this on the server side. My question is this: what is the URI that I should use for this action?
POST seems like a wrong choice as this action is idempotent. Thus, I am left with PUT. two ideas come to mind:
PUT /purchases?confirmed=true
PUT /purchaes/__all__?confirmed=true
Is there any well established convention?
EDIT
There is a third option (suggested by Markus):
PUT /confirmations/?confirmed=true
Of course, this can work and clearly has its merits. The (only) problem that I find with it is the confirmations is not an en entity in my system. In particular there is no GET /confirmations/some_id URI which may be confusing.
Firs of all, the URI you should use for this operation is whatever URI the collection of purchases returned for that action. The URI semantics shouldn't matter.
Second, when we say POST isn't idempotent, what we are saying is that the client can't assume by default that the operation is idempotent. The semantics of the POST method are entirely within your control, and that's why they must be documented and you can't rely on the client knowing beforehand what it does, as is the case with GET, PUT and DELETE.
In simple terms, having a PUT operation that isn't idempotent is a violation of the HTTP method semantics, but having a POST that is idempotent is fine.
Third, what you're doing is RPC, not REST. For instance:
PUT /purchases?confirmed=true
You're simply calling a method by passing parameters. The only way this could make sense in REST would be if you were creating or replacing a set of purchases to replace the subset where confirmed=true, which would be the exact opposite of what you want. If you want to do something like that, you should use POST, not PUT.
It's clear that your confirmation is a partial update, so you shouldn't be using PUT at all. As a general rule, if you're trying to define a separate semantics coupled to a particular resource for GET, PUT, PATCH and DELETE, you're doing wrong. Those methods should be generic and work in the exact same way for everything. If you need to couple some URI and method to a particular resource state transition, do it with POST.
I don't know the details of the API, but it looks like you're using query string parameters as payload parameters interchangeably. That's not a good idea either, since you can't treat URIs as atomic identifiers.
If your URIs were atomic, you could say this returns all unconfirmed purchases:
GET /purchases?confirmed=false
And you could document POST as the method to perform partial updates in bulk, changing the filtered subset:
POST /purchases?confirmed=false
{ "confirmed": true }
If you insist on using PUT, you should do something like this. If you have the URI below which returns a global confirmed status by reducing all purchases with AND:
GET /purchases/confirmation
{ "confirmed": False }
Then you could make something like:
PUT /purchases/confirmation
{ "confirmed": true }

ReSTful design: return an empty object as a template for create new form

My question is straighforward - I think.
Currently the following Uris exist:
http://someserver/service/item GET returns all items
http://someserver/service/item POST creates a new item
http://someserver/service/item/{id} GET returns item with id {id}
http://someserver/service/item/{id} PUT updates item with {id}
What I would like to do is return a blank 'item', like a template for creating new items which contains a list of the object parameters, their types, required or not. The reason for this is I would like to build a generic jquery 'create new' plugin completely ignorant of the data structure, which I could apply to all my new objects.
What is the best way to implement this?
I hope this makes sense and thanks for your time.
I understand an answer provided by Darrel but I would respectfully argue against it.
It seems to me that this template object (resource) is an important part of your application because you want to make it generic. It's a first class citizen resource and we're talking about REST, so it should be given a corresponding treatment. I should be able to GET the template resource, it shouldn't be "hidden" behind POST.
GET http://someserver/service/item/template
Then you can also introduce versioning and variability much more easily when you have a resource accessible via GET.
I do pretty much the same thing. I include a link in my "list of items" resource that you can POST to. The response is a template of a new item. Arguably you could also do a GET to retrieve the template, but I use the opportunity to assign a new Id to the item so my request is not idempotent.