My intent is to create a WebAPI for an IoT Device. It should give me informations about Hardware Ports, Device Status etc. My question now is, would it be okay to use it for controlling some of the ports. For example a LED which is connected to an output of the IoT Device is would be controlled like [GET] /api/led/{id}/on
or
[GET] /api/led/{id}/off
Would that contradict the actual meaning of a WebAPI?
Yes - this is not a great structure, as the GET method is supposed to be idempotent AND safe - see http://restcookbook.com/HTTP%20Methods/idempotency/ for a more detailed definition, but practically speaking what it means to say it's safe is that a GET request should not modify state or data.
So:
GET /api/led/{id}/on
should return a representation to indicate if it is on or off, but should not actually modify the state of the led. It could return true or {"on" : true } if it were on and false if it were off - whatever makes sense for your application.
To turn it on or off you should use a non-safe method, so what you could do is:
PUT /api/led/{id}/on
and make the body true or false, or possibly {"on":true} or {"on":false}
or possibly
POST /api/led/{id}/on
to turn it on and
POST /api/led/{id}/off
to turn it off.
All of the above are valid WebApi/REST techniques, but some may be more or less clear to the consumer depending on standard terminology/semantics in your context.
Related
I'm setting up an application that uses Brave to perform tracing of processing spans. Configuring it to send traces is relatively straightforward, but what I want to do is make tracing optional - that is, most of the time, nobody wants or cares about the tracing data and zipkin isn't even running.
For those sorts of configurations, it seems like one option is to implement zipkin2.reporter.Sender with a null implementation, but that seems harder than it needs to be, and still a lot of the machinery keeps running for no reason.
You can just setNoop to true on Trace
setNoop​(boolean noop)
Set true to drop data and only return noop spans regardless of sampling policy.
I have a doubt on Http methods in Rest API.I read lot about over internet on this,that we can use Put for create or update the resource and Post for creating the resource and Delete for delete a resource.
But i am saying is this mandatory?because when we write code we just put the annotation like Put,Post and Delete but what would happen if I use Delete Annotation and in side method i do something else, suppose i write add logic instead of delete.I think i can do it,similarly in others methods(Post and Put.).Then what is the significance of these Annotations.If i can do what i have mention above means write the logic for add in Delete Annotation then for me Delete is only a type of request for me and i can write any logic for add or update.
Similar i read Put is idempotent but if i write add logic instead of update then it is not idempotent.
May be i might be wrong here.Please clarify this.This is causing confusion to me and nowhere it is explained,Every where the generic statement there.
Thanks & Regards
Amitabh Pandey
i am saying is this mandatory?
Not mandatory, no.
Roy Fielding made an interesting observation 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
The same holds for the other methods -- we all agree what the request message mean (semantics), because that's what is in the standards (RFC 7230, etc). So PUT always means "please replace your current representation of the target resource with the representation I'm providing", but what your implementation does with that message is up to you.
Of course, if your implementation is surprising, there is an important caveat:
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
The point of REST is that general-purpose components can interact with your resources via the uniform interface. If your implementation doesn't match the uniform interface, then it's your bug, not a bug in the component, that things don't "just work".
i read Put is idempotent but if i write add logic instead of update then it is not idempotent.
The semantics of PUT are idempotent. If your handler for PUT requests isn't idempotent, then you have made a mistake, and your implementation has a fault. If a general purpose component needs to send multiple PUT messages (for instance, because a response was lost on an unreliable network), then that fault becomes a failure.
"Add logic" isn't necessarily not idempotent, of course -- think about adding a key and value to a dictionary; if you add the same key twice, that's the same as adding the key once.
d = {}
d[k] = v
d[k] = v # idempotent, because this is a no-op
e = {k:old}
if e[k] == old:
e[k] == new:
if e[k] == old: # Again, idempotent, because the second copy of the message is a no-op
e[k] == new
What's supposed to happen, if somebody sends a PUT request and you cannot ensure idempotent semantics, is that you should return a 405 Method Not Allowed, and make sure that your response to OPTIONS doesn't claim that PUT is supported for that resource.
I have a RESTful service for getting let's say devices. It provides very usual functionality:
GET /devices
GET /devices/:id
POST /devices
PUT /devices/:id
DELETE /devices/:id
The device object might be defined as follows:
{
id: 123,
name: "Smoke detector",
firmware: "21.0.103",
battery: "ok",
last_maintenance: "2017-07-07",
last_alarm: "2014-02-01 12:11:10",
// ...
}
There is an application that might read device state via some device specific reader. The application itself has no idea how to interpret read data, but it might ask server to do it. In our case let's assume that the data contains the following: battery status, firmware version, last alarm.
If I were implementing regular RPC service, I would create function with "parse" meaning. It means it accept the raw data and returns an updated device object (or, alternatively, only the part of the device object containing the parsed state). But I doubt that I could find a good REST solution for such function. Now I am doing it via PATCH, but I personally do not like this solution, and therefore I will not provide it here. I believe there should be good solution for such class of problems.
So the question: how should I fit my "parse" logic in REST paradigm?
POST it to a /parsed-device-state URL, which will return a 201 Created, a Location header pointing to the place where you can get the parsed data from, and if you like, return the parsed data in the 201 as well (along with an additional Content-Location header with the same value as the Location header). Or if it takes a long time to parse, use 202 Accepted, and the same Location header. The caller can then poll that provided location until the results are ready.
So the question: how should I fit my "parse" logic in REST paradigm?
How would you fit your parse logic into a web site?
You'd probably start with a bookmark. GET $BOOKMARK would return a representation of a form. The form might include an input control like a text area element that would allow the consumer to input a representation, or it might include a input control that allows the consumer to link into a file. The consumer would submit the form, and the agent would create a request from the information in the form. That would probably be a POST (you aren't likely to include an arbitrary file's representation onto the query string) to whatever resource was specified as the action of the form. The server's response would provide a representation of the result.
If parsing were a particularly slow process, then the response instead might be a representation including links to resources that could be used to track the progress of the parsing. The whole protocol in this case looks a lot like putting work on a queue, and then polling for updates.
It's the right answer to a problem that is not a great fit for HTTP:
The REST interface is designed to be efficient for large-grain hypermedia data transfer, optimizing for the common case of the Web, but resulting in an interface that is not optimal for other forms of architectural interaction.
To some degree, what you are trying to do with your function is transfer compute, which may be why it feels like you are trimming corners off of the peg to fit it in the hole.
An alternative approach, which is a better fit for HTTP, is think about transferring a representation of the behavior. The API client gets a function that understands how to parse apples into oranges, and then runs that code on the information that it keeps locally. Think java script - we get a representation of the behavior from the server (which can embed into that representation information the server has that the client will need), and then execute the result locally. Metadata in the headers describes the lifetime of the representation, in a way that is understood by any standards compliant cache.
I do hope this question is too subjective, as I am actually looking for a "best practice" that makes sense. However, the question is a bit more broad than just this case.
Lets say I have a view flag on an object (seen or not). When this object is seen, I see three options to make it true:
Let the app consumer set it by issuing an UPDATE call
When we call the GetObject method, we automatically set "seen" to true
We add a method in the API saying SetToSeen which the consumer is responsible to set
What is the favorable approach here?
for me it depends on who uses this flag.
If it is the client, then the client should update the object (maybe "seen" could read as "displayed to the user") like PUT /object/{id}/seen.
If it this is only for the server and read as "displayed to the client", then the server should update if the object was served.
I am working on large-scale web app, and within the project I am developing a REST app for outside clients. I think that this question has not very much to do with the specific technology that I am using, but just in case - it's Django.
We have a convention with the development team that REST resources always return a standard JSON object of type
{'success': <value>,
'object': <value>
'error_msg': <value>,
}
along with the status (200, 201, 403, etc....)
Examples of Django implementation:
return Response({'success': true,
'object': ...,
'error_msg': ...},
status=status.HTTP_200_OK)
The success parameter is assigned true for successful deployment of the resource, and false otherwise.
Now, the entire question here lies in what should be passed in status parameter in those cases when something bad happens - appropriate 4XX code or 200 ?. The development team suggests to ALWAYS use HTTP_200_OK, simply if something bad happened, just assign false to success. The error_msg will contain detailed error message in case of exception.
So the two alternatives among which I can't choose the right one look like this
return Response({'success': false,
'object': ...,
'error_msg': 'Details regarding the error'},
status=status.HTTP_400_BAD_REQUEST)
vs:
return Response({'success': false,
'object': ...,
'error_msg': 'Details regarding the error'},
status=status.HTTP_200_OK)
(in both cases success will equal to false. So in both cases the developer will know that something went wrong by looking at success without having to check status)
However, the very existence of different error codes leaves me with unpleasant doubt that I'm missing something about WHY people have come up with different error codes. And IN WHAT SITUATIONS my project can face trouble if it always returns the same 200 status code.After reading tons of materials, I have no material explanation why specifying appropriate error status codes could outperform the approach of returning 200 status.
HTTP codes are in my opinion a great way to get information on the result of an operation for the following reasons:
They are both machine- and human-readable (at least by developers).
They are integrated in every HTTP transaction, so every library implements mechanisms to deal with them.
The repertoire of error codes is 'standardized' and everyone knows how to deal with it, and it covers a lot of common cases (the DRF framework automatically uses some of those, such as 400, 403 or 405).
By ignoring them, you are increasing the amount of work that you have to implement on your own.
Of course, they might not be enough for particular cases. Suppose you receive a 400 code when you are submitting multiple fields to your API. If you want to know which ones are invalid and why, you still need the value of your error_msg, but the 400 code still simplifies a lot of your logic, since you can filter out a lot of other reasons why the request did not succeed (403, 405...).
Regarding your question:
And IN WHAT SITUATIONS my project can face trouble if it always returns the same 200
Well, if you implement things properly, leaving all error handling to the response date, it should never cause any trouble, but as argued earlier, I feel like this increases the complexity of the task at hand.
Please note that this are just my two cents, and there might be other opinions with better arguments for the opposite case.