I need to create a method in my REST API that will be used to perform some computation. For sake of simplicity, assume that I need to implement a method that for a given list of objects will return its length.
It should only compute the length and return to the client, so no resource will be modified server side. As it does not modify any resources, one would expect that it should be a GET request. However, as the list may be large and the objects may be complex, it looks like I need to make it as a POST request. This would however violate the standard that POST is used in REST to create resources.
What would be your solution to this problem?
First solution
According to RESTful Web Services Cookbook you can treat your computation as a resource and just GET it. For example:
-- Request
GET /computations?param1=2¶m2=2 HTTP/1.1
-- Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"result": 4
}
It sounds good for fast computations with small amount of input parameters. But if your computation isn't that then you can use second solution.
Second solution
Treat both computation and result as resources. POST computation and GET result. For example:
First you create a computation
-- Request
POST /computations HTTP/1.1
Content-Type: application/json
{
"param1": 2,
"param2": 2
}
-- Response
HTTP/1.1 201 Created
Location: /computations/1
Then you can get this computation
-- Request
GET /computations/1 HTTP/1.1
-- Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"param1": 2,
"param2": 2
}
But also you can get a result (/computations/1/result) of this computation
-- Request
GET /computations/1/result HTTP/1.1
-- Response
HTTP/1.1 204 No Content
Cache-Control: max-age=3600,must-revalidate
But oh no! There is no result yet. Server tells us to come back in an hour (Cache-Control: max-age=3600,must-revalidate) and try again. The second solution allows you to make computation asynchronous (in case when it takes a lot of time) or you can compute it once, store the result in some DB and serve it quickly when requested for the next time.
-- Request
GET /computations/1/result HTTP/1.1
-- Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"result": 4
}
Pragmatic answer: use POST.
Weasely answer: use POST. Your request contains a resource (or set of resources) that you want the server to temporarily create (the list of objects). If the server happens to delete that resource immediately after the POST has been successfully dealt with, what of it?
The moral of the story here is that with REST you always assume a resource, even if in reality one is not needed and likely not created. In the examples above, what if I want to store neither the computation resource (a JSON object that consists of parameters and some sort of operation) nor the computation result resource? I cannot. I can either
Treat this as a fake resource with GET (pretend that it exists) or
Create two resources with a single POST - one for the computation and one for its result - and then use the corresponding GET to retrieve either of those.
A sneaky assumption here also is that there is NO POST for /computation/<computaiton_id>/result because results are only created via computations.
Related
I'm calling a backend REST endpoint that takes in a query param and searches for a matching result /people?name=joe, and I'm wondering what status code and return data I should be returning when no object is found in the DB matching name=joe.
Things I've considered:
If I was directly hitting an endpoint /people/joe and it was not found, then I would definitely return 404.
If I was hitting an endpoint that returned a list of results for a query like if /people?name=joe was supposed to return ALL people named joe, then I would just return 200 with an empty list as the body. But in my case, I can only have one object for each name, so I'm not returning a list, so this doesn't apply here.
So this is a different case where I'm hitting an endpoint and passing in a query param to "search" for some data. And it is expected that in many cases, the data won't exist yet.
This seems pretty similar to the first bullet point above, but I don't like returning a 404 here since this is not necessarily an error.
Should I return a 200 but with an empty object {} as the body, and then my frontend should check if body == {} then take that to mean no data found?
Or should I still return a 404 here? Again, this is not really an error in my case which is why I don't want to use a 404, but if that makes most sense, then I could.
Easy parts first - status codes are metadata of the transfer-of-documents-over-a-network domain (Webber, 2011). In the context of a GET request (which asks for the current selected representation of a resource), a 200 response indicates that the response content is a representation of the resource (as opposed, for example, to being a representation of an error).
Furthermore, URI are opaque: general purpose HTTP components do not make assumptions about the semantics of resources based on the spelling of their identifiers. In other words, the "rules" are exactly the same for both
/people/joe
/people?joe
/people?name=joe
...
So at the HTTP level, the answers to your question are easy: if there's a current representation, then you reply to GET requests with a 200 status and copy the current representation into the response content.
The hard parts are deciding when there is a current representation, and what it looks like. REST and HTTP don't have anything to say about that, really. It's a resource design concern.
For example, this is interaction "follows all the rules":
GET /people?name=dave HTTP/1.1
HTTP/1.1 200 OK
Content-Location: /people?name=dave
Content-Type: text/plain
Dave's not here, man
HTTP is a general purpose mechanism for asking for documents/transmitting documents over a network, but it is agnostic about what documents look like and what keys we use to identify documents in the store.
If you are dealing with representations that describe zero or exactly one things, it can still be reasonable to use a list which is either empty or contains exactly one element (if you are familiar with Option/Optional/Maybe: same idea, we're presenting something with the semantics of an iterable collection)
HTTP/1.1 200 OK
Content-Location: /people?name=dave
Content-Type: application/json
[]
HTTP/1.1 200 OK
Content-Location: /people?name=bob
Content-Type: application/json
[{
...
}]
I agree that 200 and empty collection is better than 404 in your scenario. I don't like the idea of looking for {}, it is not explicit enough.
Possible ways of doing this:
200 ok
{
items:[]
}
200 ok
{
size:0//,
//items:undefined
}
200 ok
[]
206 Partial Content
Accept-Ranges: items
Content-Range: items 0-0/0
// []
I didn't find useful information about which methods status is correct for absent object in db.
For example I have deleted user with id = 1, but someone try to get it's information thought GET method with query params id=1.
Which status will be right: 404, 204, 400,406 or 410?
I didn't find useful information about which methods status is correct for absent object in db.
Yup, that's right - HTTP status codes don't tell you anything about rows in a database, what they tell you about are documents ( "resources" ) in a document store.
More precisely, the HTTP status code is metadata that tells general purpose components (like a web browser, or a cache) what's in the message-body of the response.
Depending on what document you put into the message-body, the appropriate status code could be any of:
200
404
410
200 announce that the message-body is a document (more broadly, a current representation of the resource). 404 and 410 (and all 4xx and 5xx status codes) announce that the message-body is a representation of the explanation of the error.
404 indicates that the document identified by the effective target uri of the request doesn't exist right now, but it might exist later; you can attach caching metadata to communicate when the might check again.
410 indicates that the document identified by the effective target uri of the request doesn't exist right now, and that condition is likely permanent. That permanence implies that clients can delete bookmarks, and remote links to the document should be removed, and so on.
If you recycle ids, or if deletes ids can be restored, then 410 isn't an appropriate choice.
In some APIs, resources have current representations even when there is no matching information in the database.
In other words, the current representation of the resource might be an empty document
200 OK HTTP/2
Content-Type: text/plain
Content-Length: 0
or it could be a null object
200 OK HTTP/2
Content-Type: application/json
Content-Length: 4
null
or it could be an empty list
200 OK HTTP/2
Content-Type: application/json
Content-Length: 2
[]
or an empty object
200 OK HTTP/2
Content-Type: application/json
Content-Length: 2
{}
or a meme
200 OK HTTP/2
Content-Type: text/plain
Content-Length: 36
This space intentionally left blank.
The status code to use follows from the decision to use a sort of "default" representation of our document when there is no specific information available.
The more common decision, of course, is to choose not to provide default representations, but instead announce that the client has made a mistake (in which case the 4xx class of status code is the correct starting point).
Isn't it write to return 204(NO CONTENT) status or something similar? 'Cause I think 200 is not fully informative status
Maybe - there's some ambiguity in the HTTP standard, and because of that ambiguity I tend to be biased against 204 (today; if you look up some of my older answers, I was much likely to try 204 in the past).
RFC 7231, Section 6.3.1
Aside from responses to CONNECT, a 200 response always has a payload, though an origin server MAY generate a payload body of zero length. If no payload is desired, an origin server ought to send 204 (No Content) instead.
So we have two different ways to send zero bytes of data back to the client; either 200 with Content-Length set to zero, or 204.
Are those two things the same?
The answer seems to be "not quite"; there's a subtle difference documented in section 6.3.5
The 204 response allows a server to indicate that the action has been successfully applied to the target resource, while implying that the user agent does not need to traverse away from its current "document view" (if any).
Now, think about that in the context of a web browser. If I click a link that points to an empty file, a 200 response would mean that the browser would traverse away from the current "document view" to show me the empty file. But the language of 204 suggests that instead the browser should stay put, and just indicate that the empty file was successfully downloaded.
Note: I haven't done any experiments to see if browsers do act that way; my only claim is that staying in place is the specified behavior.
My reading of the specification is that 204 is designed to support a use case that only arises in the context of unsafe actions, like PUT. You can see hints of that as far back as HTTP/1.0
This response is primarily intended to allow input for scripts or other actions to take place without causing a change to the user agent's active document view. The response may include new metainformation in the form of entity headers, which should apply to the document currently in the user agent's active view.
In short, responding with a 204 to a GET request is placing a bet that the authors of general purpose components have interpreted an ambiguous part of the specification the same way that you do -- and I don't like that bet at all. Much more reliable to use the well understood 200 response, and avoid the unnecessary ambiguity.
I have a simple question that I cannot find the answer to.
My colleague is currently making a REST Api for an application, and we have a call that simply checks some information, and returns either true or false. However, we do not know what to call this type of request, as it does not retrive any resources or insert anyhing, it simply checks some information passed into the query. As far as I can understand, a GET has to retrive a resource, which this call isn't doing
What I understand is, resource in this case is either true or false. While calling the API you will expect response either true or false on the basis of information processed by API server (status will be always 200). So a GET method is still suitable for this case.
If you are not interested in response body and you want data like response code and header details, go with HEAD.
There might be a different way to express 'checking some information', and it's important to be a bit more specific as to what that means.
So lets take an arbitrary example. You're modelling blog posts and want to know if some blog post is set to 'draft'.
The 'draft' status can be its own resource, for example:
/posts/hello-world/is-draft
Doing a GET request on the is-draft resource can yield:
{
"is-draft": true
}
So to model arbitrary things as resources, the best way to think about this is to look at the result of the operation as the 'representation' and the 'thing you want to know' as the URI.
As far as I can understand, a GET has to retrive a resource, which this call isn't doing
Technically, it is retrieving a resource; see Fielding
The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource.
The resource, in this case, might not load an entity in your data model, but that's OK. Not all resources have to.
Technically, I think what you have there is a "function"; all of the information that you need to compute the result is present within the URI itself? Which would mean that, if the client knew how to do the computation (and had the compute resources available), then the client would be capable of doing the work for itself.
But there's nothing wrong with having a resource that is "the result of a function".
In some API, you'll see predicates (functions that return true/false) implemented as resources that only exist (more precisely, only have "representations") if the evaluation is true.
GET /predicate?true
204 No Content
GET /predicate?false
404 Not Found
The fact that you don't need to consider the resources "state" to compute the correct response to the query is an implementation detail hidden behind the uniform interface.
It's hard to tell by the level of details you provided your question. But if you need to check whether a resource exists or not, you can use HEAD. It's identical to GET, but it doesn't return a representation in the response payload: it returns just the status code and the response headers.
Consider the following request HEAD request:
HEAD /postal-codes/10001 HTTP/1.1
Host: example.org
Content-Type: application/json
It should return 200 for a resource that exists:
HTTP/1.1 200 OK
Content-Type: application/json
And 404 for a resource that doesn't exists:
HTTP/1.1 404 Not Found
Content-Type: application/json
Depending on your needs, you could address it with POST, which can be seen as a catch all verb.
For example, consider the following request and responses:
POST /postal-codes/validation HTTP/1.1
Host: example.org
Content-Type: application/json
{ "postal-code": "10001" }
HTTP/1.1 200 OK
Content-Type: application/json
{ "postal-code": "10001", "status": "valid" }
HTTP/1.1 200 OK
Content-Type: application/json
{ "postal-code": "10001", "status": "invalid" }
Every single resource I'va come across on Internet always describes very well what you can do with the GET operation, how it works and so on, bu it never explains the POST/PUT/DELETE and particularly the format of the data you pass in the HTTP body (I'm using JSON). It always says "you can make a post request and pass the appropriate data in the body".
I am struggling with what I can do and not. For example I want to know if it is possible to update one field of one entry by just sending the updated value, and not the entire object.
Is there any document that explains clearly the possibilities and limitations?
Thanks a lot.
Easy to read documentation is here: http://www.odata.org/developers/protocols
If you want all the dirty details and a strict language you can read this document: http://msdn.microsoft.com/en-us/library/dd541188(PROT.10).aspx
You can modify a value of a single property by sending a PUT request.
For example if you send a GET to this URL:
http://services.odata.org/(S(kupqbta5wqnfz2cln1qk052x))/OData/OData.svc/Products(0)/Name
And you request JSON (through an Accept header) the response will be:
{
"d" : {
"Name": "Bread"
}
}
The "d" wrapper is there only to avoid XSS attacks so that must not be included in the requests, but the rest stays the same, so if you then send a PUT request like this:
PUT http://services.odata.org/(S(kupqbta5wqnfz2cln1qk052x))/OData/OData.svc/Products(0)/Name HTTP/1.1
Host: services.odata.org
Content-Type: application/json
Content-Length: 20
{
"Name": "Meat"
}
It will update the property Name to value Meat. You can also send a PUT to the value itself, in which case the URL would end with $value (denotes the raw value of the property) like this:
PUT http://services.odata.org/(S(kupqbta5wqnfz2cln1qk052x))/OData/OData.svc/Products(0)/Name/$value HTTP/1.1
Host: services.odata.org
Content-Type: text/plain
Content-Length: 4
Meat
Note that this only works on primitive properties though.
The sample service on the odata.org allows you to make modifications (guarded by the session key in the URL), so can play with it there.
Google for the HTTP 1.1 specification.
How should a random number generator properly be implemented in REST?
GET RANDOM/
or..
POST RANDOM/
The server returns a different random number each time.
I can see arguments for both ways.
I'd say this is the same as for a page returned that contains the current time - and many of these are done using GET. Abstractly, fetching a random number (or time) the server's state doesn't change - both time and random numbers can be described as an observation of an external event. E.g. http://random.org use atmospheric noise.
GET seems most appropriate, although caching will need to be disabled via appropriate headers, e.g.
Expires: <Current Time>
Last-Modified: <Current Time>
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
If you want to ensure that the served content is already expired:
To mark a response as "already
expired," an origin server sends an
Expires date that is equal to the Date
header value. (See the rules for
expiration calculations in section
13.2.4.)
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
Definitely GET. Even though it might modify server-side state (if it uses a pseudo-RNG), that's just an implementation detail the client shouldn't care about.
definition of REST-call with GET: the result have to be the same -> not GET.
definition of REST-call with PUT: the result of the call can be repeatable, the server should not have problem with it -> use PUT
POST is the weakest method and can used if other are not useful.
Why not GET: the result of GET-call can be cachet (cache-header, etag oder transparent proxies) and you dont will get random results ...