Best REST practice for responce "GET" method status? - rest

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.

Related

REST API - what to return when query for a GET does not find a result

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
// []

Which http status code for 'entity not found'?

/persons?age=18
Imagine a search does not return any results (means: no entity found for the request).
If I'd return a 404 here, that would suggest that maybe the /persons path is invalid entirely.
Is there any accepted status code that could be return if the request was valid in general (means: the path exists, and the request parameters have been valid), but still there is no data to return?
204 is not suitable either, as this is used to tell the user "your request was 200 OK, but there will never be a response body to your request" (like for modifications).
Is there any accepted status code that could be return if the request was valid in general (means: the path exists, and the request parameters have been valid), but still there is no data to return?
200 is appropriate when the resource has a representation, even if that representation is an empty list.
# Request:
GET /persons?age=18
# Response:
200 OK
[]
Think "web search page that returns no results", downloading an empty file.
Jim Webber's 2011 talk may help with perspective here: the status codes and headers belong to the "transferring documents over a network" domain, not to your domain application protocol. The components that are specific to your application should be paying attention to the messages in the body of the response; the meta data is directed at general purpose components that are transferring documents.
Actually you should return 200.
The number of entities found does not change the http code.

REST API Design: Respond with 406 or 404 if a resource is not available in a requested representation

We have a REST API to fetch binary files from the server.
The requests look like
GET /documents/e62dd3f6-18b0-4661-92c6-51c7258f9550 HTTP/1.1
Accept: application/octet-stream
For every response indicating an error, we'd like to give a reason in JSON.
The problem is now, that as the response is not of the same content type as the client requested.
But what kind of response should the server produce?
Currently, it responds with a
HTTP / 1.1 406 Not Acceptable
Content-Type: application/json
{
reason: "blabla"
...
}
Which seems wrong to me, as the underlying issue is, that the resource is not existing and not the client requesting the wrong content type.
But the question is, what would be the right way to deal with such situations?
Is it ok, to respond with 404 + application/json although application/octet-stream was requested
Is it ok, to respond with 406 + application/json, as the client did not specify an application/json as an acceptable type
Should spec been extended so that the client should use the q-param - for example, application/octet-stream, application/json;q=0.1
Other options?
If no representation can be found for the requested resource (because it doesn't exist or because the server wishes to "hide" its existence), the server should return 404.
If the client requests a particular representation in the Accept header and the server is not available to provide such representation, the server could either:
Return 406 along with a list of the available representations. (see note** below)
Simply ignore the Accept header and return a default representation of the resource.
See the following quote from the RFC 7231, the document the defines the content and semantics of the HTTP/1.1 protocol:
A request without any Accept header field implies that the user agent will accept any media type in response. If the header field is present in a request and none of the available representations for the response have a media type that is listed as acceptable, the origin server can either honor the header field by sending a 406 (Not Acceptable) response or disregard the header field by treating the response as if it is not subject to content negotiation.
Mozilla also recommends the following regarding 406:
In practice, this error is very rarely used. Instead of responding using this error code, which would be cryptic for the end user and difficult to fix, servers ignore the relevant header and serve an actual page to the user. It is assumed that even if the user won't be completely happy, they will prefer this to an error code.
** Regarding the list of available representations, see this answer.

REST Api naming convention?

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" }

What status code should we return if the POST succeeds but does not result in creating anything new?

We have an endpoint which when you post create a new version of resource and returns a 201 and the location of the newly created resource. It determines the new version number based on a comparison of the current version and the version being posted (using a semver like ruleset).
If the version you post is identical to the existing version then no version number is updated. What should we return in this case?
We could just return a 201 even though we have not technically created anything.
I don't want to return a 409 as its not really a conflict, like when you post something with the same id. If you posted the same thing when the existing version was slightly different then you would happily get a 201.
We could just return a 200, but then that would seem weird, and increases the response codes that the users have to deal with
Does the idempotency of the 201 response matter?
Any better suggestions?
How about 303 - See Other? Seems to fit. I draw your attention to this sentence
from the spec at https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
This method exists primarily to allow the output of a POST-activated script to redirect the user agent to a selected resource.
That sounds like what you want to do to me. Here's the rest of it.
10.3.4 303 See Other
The response to the request can be found under a different URI and SHOULD be retrieved using a GET method on that resource. This method exists primarily to allow the output of a POST-activated script to redirect the user agent to a selected resource. The new URI is not a substitute reference for the originally requested resource. The 303 response MUST NOT be cached, but the response to the second (redirected) request might be cacheable.
The different URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s).
Note: Many pre-HTTP/1.1 user agents do not understand the 303
status. When interoperability with such clients is a concern, the
302 status code may be used instead, since most user agents react
to a 302 response as described here for 303
I am a bit puzzled by the other answers as some get it almost right. So, let's clear up things a bit. If all requests are indeed performed with the POST method, in the context of ReSTfulness, they are supposed to modify state on the target server. Otherwise, the meaning of POST is a bit relaxed as you can see in RFC 7231, sec. 4.3.3.
Since the intent of the requests is to create a new version of a resource, they have failed if a version with the given presentation already exists. This would disqualify any 2xx-class response codes. From section 6.3:
The 2xx (Successful) class of status code indicates that the client's request was successfully received, understood, and accepted.
If you absolutely wanted to, you could go for 202/Accepted, which "is intentionally noncommittal." This is a bit of a stretch, though, as this status code is intended for queued processing. I would advise against it.
The 204/No Content code suggested by others is a bit of a poor choice. It were absolutely correct if you POSTed to the resource you were updating, though.
As the result is neither informational (1xx) nor a fault by the server (5xx). Let us have a look at the 3xx class first. From section 6.4:
The 3xx (Redirection) class of status code indicates that further action needs to be taken by the user agent in order to fulfill the request.
One of the most prominent one here would be 304/Not Modified. While sounding like a perfect fit, this code is unfortunately not applicable here. It can only be returned in response to conditional GET or HEAD requests.
302/Found may sound like the next best fit. However, this code is intended for temporary redirects, which is in all likelyhood not what you want.
As has been suggested here, 303/See Other is indeed a good choice:
The 303 (See Other) status code indicates that the server is redirecting the user agent to a different resource [...] which is intended to provide an indirect response to the original request.
[...]
This status code is applicable to any HTTP method. It is primarily used to allow the output of a POST action to redirect the user agent to a selected resource
All other 3xx codes are dealing with various forms of redirects that hardly relate to the situation here.
A final look, 4xx-class of status codes. From RFC 7231, sec. 6.5:
The 4xx (Client Error) class of status code indicates that the client seems to have erred. Except when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method.
Very few of these are actually deeling with the request body. Two of those who do would stand out here: One is 400/Bad Request, which is by design overly broad. It is - if you will - a catch-all solution. However, this would imply that the request body is malformed (as in syntactically incorrect) in some way, which is probably not the case.
More interesting is 409/Conflict. From the RFC (emphasis mine):
The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource.
The wording of the definition places this code close to the PUT method, but is not exclusive. To reiterate the definition of the 4xx codes:
These status codes are applicable to any request method.
422/Unprocessable Entity is a contender, but it implies a semantic error, which really isn't the case here.
Ultimately (drumroll) the final piece of the puzzle could be found in section 4.3.3:
If the result of processing a POST would be equivalent to a representation of an existing resource, an origin server MAY redirect the user agent to that resource by sending a 303 (See Other) response with the existing resource's identifier in the Location field.
Note the "MAY." So you can really choose between 303 and 409. I feel 409 were the better fit, as clearly an earlier request introduced a state that is incompatible with the current one. OTOH, 303 may be the politer way to go and is closer to the standard. Either way, as a consumer of your API, I would really like to know if my requests failed. And be it by not having any effect whatsoever.
If nothing has been created by the operation, 201 is not suitable for that:
6.3.2. 201 Created
The 201 (Created) status code indicates that the request has been fulfilled and has resulted in one or more new resources being created. [...]
See below some options you could consider if the operation succeeds:
6.3.1. 200 OK
The 200 (OK) status code indicates that the request has succeeded. The payload sent in a 200 response depends on the request method. For the methods defined by this specification, the intended meaning of the payload can be summarized as:
[...]
POST: a representation of the status of, or results obtained from, the action;
[...]
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. [...]
6.3.5. 204 No Content
The 204 (No Content) status code indicates that the server has successfully fulfilled the request and that there is no additional content to send in the response payload body. [...]
If the operation fails:
6.5.1. 400 Bad Request
The 400 (Bad Request) status code indicates that the server cannot will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
11.2. 422 Unprocessable Entity
The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415 (Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.
A 201 Created should be used whenever you creating a new resource without doubt.
As defined in HTTP Method Definitions RFC, either200 Ok or 204 No Contentis an appropriate response if the operation does not create a new resource depending on the response body content.
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.
If a resource has been created on the origin server, the response
SHOULD be 201 (Created) and contain an entity which describes the
status of the request and refers to the new resource, and a Location
header (see section 14.30).
Now, coming back to your original question about what to use when the operation is successful and there is nothing to return, you should use 204 No Content. This status code is specifically meant for scenarios where the requested operation is successfully completed but there is no additional relevant information that the server can provide.
The 204 (No Content) status code indicates that the server has successfully fulfilled the request and that there is no additional content to send in the response payload body.
I don't think that for this case the idempotency is an issue, because the state of the system is not the same as it was in the inicial request, because the entity now exists, so you can respond with a different code.
200 should be fine, but it is a little weird as you said.
I have never use this, but I read that for some case you should redirect with a 302, to make a get for other resource, in this case I think this apply, return a 302 and make a get pointing for the old semver, assuming that you have a get endpoint for this entity.
If the POST'd resource has the same version number, but different data, then a 409 would be fitting. But if the data is the same as what's already stored, then a 409 might not be required. Through process of elimination I would say 200 OK would be fine.
We could just return a 200, but then that would seem weird, and increases the response codes that the users have to deal with
If this is a costly concern, consider eliminating the 201, not the 200. The fact of the matter is that for any decently complex service there may be at some point a situation where a 20X (where X is not 0) is applicable. So does that mean we code with each of the 20X responses in mind and spend time checking if our services has situations where 20X is preferred over 200? I suspect not. So unless there is a specific reason to respond with a 20X, for example to deal with a specific use case, then just use 200 and reduce the amount of coding and documenting required. I suspect for most scenarios, the calling client does not care.
Ultimately, the correct answer probably depends on whatever client is consuming your API. If you are building the client too, you could do whatever you prefer... (Just don't get too crazy.)
Assuming you are writing the API and client:
My opinion/suggestion is...
If there IS a new version number: The 201 HTTP status code would fit will.
If there is NOT a new version number: The 200 or 204 HTTP status code would fit well.
If there is no benefit to the client knowing the version number has changed or is the same: Send the 200 HTTP status code.
If you don't control the client consuming your API: Obviously defer to what they expect.
You may also wish review all of the HTTP Status Codes in the HTTP RFC spec. The above status codes also link directly to the relevant section.
201 : when new version is created
202 : when existing version is updated
204 : when request is accepted but no processing is done
by def, 204 = No Content
The server has fulfilled the request but does not need to return an
entity-body, and might want to return updated metainformation. The
response MAY include new or updated metainformation in the form of
entity-headers, which if present SHOULD be associated with the
requested variant.
If the client is a user agent, it SHOULD NOT change its document view
from that which caused the request to be sent. This response is
primarily intended to allow input for actions to take place without
causing a change to the user agent's active document view, although
any new or updated metainformation SHOULD be applied to the document
currently in the user agent's active view.
The 204 response MUST NOT include a message-body, and thus is always
terminated by the first empty line after the header fields.
So its slight tangential to your needs but I think its the best fit.