问题
For example you run a GET request for users/9 but there is no user with id #9.
Which is the best response code?
- 200 OK
- 202 Accepted
- 204 No Content
- 400 Bad Request
- 404 Not Found
回答1:
TL;DR: Use 404
See This Blog. It explains it very well.
Summary of the blog's comments on 204:
204 No Contentis not terribly useful as a response code for a browser (although according to the HTTP spec browsers do need to understand it as a 'don't change the view' response code).204 No Contentis however, very useful for ajax web services which may want to indicate success without having to return something. (Especially in cases likeDELETEorPOSTs that don't require feedback).
The answer, therefore, to your question is use 404 in your case. 204 is a specialized reponse code that you shouldn't often return to a browser in response to a GET.
The other response codes that are even less appropriate than 204 and 404:
200should be returned with the body of whatever you successfully fetched. Not appropriate when the entity you're fetching doesn't exist.202is used when the server has begun work on an object but the object isn't fully ready yet. Certainly not the case here. You haven't begun, nor will you begin, construction of user 9 in response to aGETrequest. That breaks all sorts of rules.400is used in response to a poorly formatted HTTP request (for instance malformed http headers, incorrectly ordered segments, etc). This will almost certainly be handled by whatever framework you're using. You shouldn't have to deal with this unless you're writing your own server from scratch. Edit: Newer RFCs now allow for 400 to be used for semantically invalid requests.
Wikipedia's description of the HTTP status codes are particularly helpful. You can also see the definitions in the HTTP/1.1 RFC2616 document at www.w3.org
回答2:
I strongly oppose 404 in favour of 204 or 200 with empty data.
The request was received and properly processed - it did trigger application code on the server, thus one cannot really say that it was a client error and thus the whole class of client error codes (4xx) is not fitting.
More importantly, 404 can happen for a number of technical reasons. E.g. the application being temporarily deactivated or uninstalled on the server, proxy connection issues and whatnot. Therefore the client cannot distinguish between a 404 that means "empty result set" and a 404 that means "the service cannot be found, try again later".
This can be fatal: Imagine an accounting service in your company that lists all the employees that are due to an annual bonus. Unfortunately, the one time when it is called it returns a 404. Does that mean that no-one is due for a bonus, or that the application is currently down for a new deployment?
-> For applications that care about the quality of their data, 404 therefore is pretty much a no-go.
Also, many client frameworks respond to a 404 by throwing an exception with no further questions asked. This forces the client developer to catch that exception, to evaluate it, and then to decide based on that whether to log it as an error that is picked up by e.g. a monitoring component or whether to ignore it. That doesn't seem pretty to me either.
The only advantage of 404 over 204 is that it can return a response entity that may contain some information about why the requested resource was not found. But if that really is relevant, then one may also consider using a 200 OK response and design the system in a way that allows for error responses in the payload data. Alternatively, one could use the payload of the 404 response to return structured information to the caller. If he receives e.g. a html page instead of XML or JSON that he can parse, then that is a good indicator that something technical went wrong instead of a "no result" reply that may be valid from the caller's point of view. Or one could use a HTTP response header for that.
Still i would prefer a 204 or 200 with empty response though. That way the status of the technical execution of the request is separated from the logical result of the request. 2xx means "technical execution ok, this is the result, deal with it".
I think in most cases it should be left to the client to decide whether an empty result is acceptable or not. By returning 404 despite of a correct technical execution the client may decide to consider cases to be errors that simply are no errors.
Another quick analogy: Returning 404 for "no result found" is like throwing a DatabaseConnectionException if a SQL query returned no results. It can get the job done, but there are lots of possible technical causes that throw the same exception which then would be mistaken for a valid result.
回答3:
At first, I thought a 204 would make sense, but after the discussions, I believe 404 is the only true correct response. Consider the following data:
Users: John, Peter
METHOD URL STATUS RESPONSE
GET /users 200 [John, Peter]
GET /users/john 200 John
GET /users/kyle 404 Not found
GET /users?name=kyle` 200 []
DELETE /users/john 204 No Content
Some background:
the search returns an array, it just didn't have any matches but it has content: an empty array.
404 is of course best known for url's that aren't supported by the requested server, but a missing resource is in fact the same.
Even though/users/:nameis matched withusers/kyle, the user Kyle is not available resource so a 404 still applies. It isn't a search query, it is a direct reference by a dynamic url, so 404 it is.
Anyway, my two cents :)
回答4:
If it's expected that the resource exists, but it might be empty, I would argue that it might be easier to just get a 200 OK with a representation that indicates that the thing is empty.
So I'd rather have /things return a 200 OK with {"Items": []} than a 204 with nothing at all, because in this way a collection with 0 items can be treated just the same as a collection with one or more item in it.
I'd just leave the 204 No Content for PUTs and DELETEs, where it might be the case that there really is no useful representation.
In the case that /thing/9 really doesn't exist, a 404 is appropriate.
回答5:
In previous projects, I've used 404. If there's no user 9, then the object was not found. Therefore 404 Not Found is appropriate.
For object exists, but there is no data, 204 No Content would be appropriate. I think in your case, the object does not exist though.
回答6:
According to w3 post,
200 OK
The request has succeeded. The information returned with the response is dependent on the method used in the request
202 Accepted
The request has been accepted for processing, but the processing has not been completed.
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.
400 Bad Request
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications
401 Unauthorized
The request requires user authentication. The response MUST include a WWW-Authenticate header field
404 Not Found
The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent
回答7:
To summarize or simplify,
2xx: Optional data: Well formed URI: Criteria is not part of URI: If the criteria is optional that can be specified in @RequestBody and @RequestParam should lead to 2xx. Example: filter by name / status
4xx: Expected data : Not well formed URI : Criteria is part of URI : If the criteria is mandatory that can only be specified in @PathVariable then it should lead to 4xx. Example: lookup by unique id.
Thus for the asked situation: "users/9" would be 4xx (possibly 404) But for "users?name=superman" should be 2xx (possibly 204)
回答8:
There are two questions asked. One in the title and one in the example. I think this has partly led to the amount of dispute about which response is appropriate.
The question title asks about empty data. Empty data is still data but is not the same as no data. So this suggests requesting a result set, i.e. a list, perhaps from /users. If a list is empty it is still a list therefore a 204 (No Content) is most appropriate. You have just asked for a list of users and been provided with one, it just happens to have no content.
The example provided instead asks about a specific object, a user, /users/9. If user #9 is not found then no user object is returned. You asked for a specific resource (a user object) and were not given it because it was not found, so a 404 is appropriate.
I think the way to work this out is if you can use the response in the way you would expect without adding any conditional statement, then use a 204 otherwise use a 404.
In my examples I can iterate over an empty list without checking to see if it has content, but I can't display user object data on a null object without breaking something or adding a check to see if it is null.
You could of course return an object using the null object pattern if that suits your needs but that is a discussion for another thread.
回答9:
What the existing answers do not elaborate on is that it makes a difference whether you use path parameters or query parameters.
- In case of path parameters, the parameter is part of the resource path. In case of
/users/9, the response should be404because that resource was not found./users/9is the resource, and the result is unary, or an error, it doesn't exist. This is not a monad. - In case of query parameters, the parameter is not part of the resource path. In case of
/users?id=9, the response should be204because the resource/userswas found but it could not return any data. The resource/usersexists and the result is n-ary, it exists even if it is empty. Ifidis unique, this is a monad.
Whether to use path parameters or query parameters depends on the use case. I prefer path parameters for mandatory, normative, or identifying arguments and query parameters for optional, non-normative, or attributing arguments (like paging, collation locale and stuff). In a REST API, I would use /users/9 not /users?id=9 especially because of the possible nesting to get "child records" like /users/9/ssh-keys/0 to get the first public ssh key or /users/9/address/2 to get the third postal address.
I prefer using 404. Here's why:
- Calls for unary (1 result) and n-ary (n results) methods should not vary for no good reason. I like to have the same response codes if possible. The number of expected results is of course a difference, say, you expect the body to be an object (unary) or an array of objects (n-ary).
- For n-ary, I would return an array, and in case there are not results, I would not return no set (no document), I would return an empty set (empty document, like empty array in JSON or empty element in XML). That is, it's still 200 but with zero records. There's no reason to put this information on the wire other than in the body.
204is like avoidmethod. I would not use it forGET, only forPOST,PUT, andDELETE. I make an exception in case ofGETwhere the identifiers are query parameters not path parameters.- Not finding the record is like
NoSuchElementException,ArrayIndexOutOfBoundsExceptionor something like that, caused by the client using an id that doesn't exist, so, it's a client error. - From a code perspective, getting
204means an additional branch in the code that could be avoided. It complicates client code, and in some cases it also complicates server code (depending on whether you use entity/model monads or plain entities/models; and I strongly recommend staying away from entity/model monads, it can lead to nasty bugs where because of the monad you think an operation is successful and return 200 or 204 when you should actually have returned something else). - Client code is easier to write and understand if 2xx means the server did what the client requested, and 4xx means the server didn't do what the client requested and it's the client's fault. Not giving the client the record that the client requested by id is the client's fault, because the client requested an id that doesn't exist.
Last but not least: Consistency
GET /users/9PUT /users/9andDELETE /users/9
PUT /users/9 and DELETE /users/9 already have to return 204 in case of successful update or deletion. So what should they return in case user 9 didn't exist? It makes no sense having the same situation presented as different status codes depending on the HTTP method used.
Besides, not a normative, but a cultural reason: If 204 is used for GET /users/9 next thing that will happen in the project is that somebody thinks returning 204 is good for n-ary methods. And that complicates client code, because instead of just checking for 2xx and then decoding the body, the client now has to specifically check for 204 and in that case skip decoding the body. Bud what does the client do instead? Create an empty array? Why not have that on the wire, then? If the client creates the empty array, 204 is a form of stupid compression. If the client uses null instead, a whole different can of worms is opened.
回答10:
After looking in question, you should not use 404 why?
Based on RFC 7231 the correct status code is 204
In the anwsers above I noticed 1 small missunderstanding:
1.- the resource is: /users
2.- /users/8 is not the resource, this is: the resource /users with route parameter 8, consumer maybe cannot notice it and does not know the difference, but publisher does and must know this!... so he must return an accurate response for consumers. period.
so:
Based on the RFC: 404 is incorrect because the resources /users is found, but the logic executed using the parameter 8 did not found any content to return as a response, so the correct answer is: 204
The main point here is: 404 not even the resource was found to process the internal logic
204 is a: I found the resource, the logic was executed but I did not found any data using your criteria given in the route parameter so I cant return anything to you. Im sorry, verify your criteria and call me again.
200: ok i found the resource, the logic was executed (even when Im not forced to return anything) take this and use it at your will.
205: (the best option of a GET response) I found the resource, the logic was executed, I have some content for you, use it well, oh by the way if your are going to share this in a view please refresh the view to display it.
Hope it helps.
回答11:
Twitter uses 404 with a custom error message like "No data found".
Ref: https://developer.twitter.com/en/docs/basics/response-codes.html
回答12:
204 is more appropriate. Especially when you have a alert system to ensure you website is secure, 404 in this case would cause confusion because you don't know some 404 alerts is backend errors or normal requests but response empty.
回答13:
I'd say, neither is really appropriate. As has been said – e.g. by @anneb, I, too, think that part of the problems arises from using an HTTP response code to transport a status relating to a RESTful service. Anything the REST service has to say about its own processing should be transported by means of REST specific codes.
1
I'd argue that, if the HTTP server finds any service that is ready to answer a request it was sent, it should not respond with an HTTP 404 – in the end, something was found by the server – unless told so explicitly by the service that processes the request.
Let's assume for a moment the following URL: http://example.com/service/return/test.
- Case A is that the server is “simply looking for the file on the file system“. If it is not present,
404is correct. The same is true, if it asks some kind of service to deliver exactly this file and that service tells it that nothing of that name exists. - In case B, the server does not work with “real” files but actually the request is processed by some other service – e.g. some kind of templating system. Here, the server cannot make any claim about the existence of the resource as it knows nothing about it (unless told by the service handling it).
Without any response from the service explicitly requiring a different behaviour, the HTTP server can only say 3 things:
503if the service that is supposed to handle the request is not running or responding;200otherwise as the HTTP server can actually satisfy the request – no matter what the service will say later;400or404to indicate that there is no such service (as opposed to “exists but offline”) and nothing else was found.
2
To get back to the question at hand: I think the cleanest approach would be to not use an HTTP any response code at all other than said before. If the service is present and responding, the HTTP code should be 200. The response should contain the status the service returned in a separate header – here, the service can say
REST:EMPTYe.g. if it was asked to search for sth. and that research returned empty;REST:NOT FOUNDif it was asked specifically for sth. “ID-like” – be that a file name or a resource by ID or entry No. 24, etc. – and that specific resource was not found (usually, one specific resource was requested and not found);REST:INVALIDif any part of the request it was sent is not recognized by the service.
(note that I prefixed these with “REST:” on purpose to mark the fact that while these may have the same values or wording as do HTTP response codes, they are sth. completely different)
3
Let's get back to the URL above and inspect case B where service indicates to the HTTP server that it does not handle this request itself but passes it on to SERVICE. HTTP only serves out what it is handed back by SERVICE, it does not know anything about the return/test portion as that is handeled by SERVICE. If that service is running, HTTP should return 200 as it did indeed find something to handle the request.
The status returned by SERVICE (and which, as said above, would like to see in a separate header) depends on what action is actually expected:
- if
return/testasks for a specific resource: if it exists, return it with a status ofREST:FOUND; if that resource does not exist, returnREST:NOT FOUND; this could be extended to returnREST:GONEif we know it once existed and will not return, andREST:MOVEDif we know it has gone hollywood - if
return/testis considered a search or filter-like operation: if the result set is empty, return an empty set in the type requested and a status ofREST:EMPTY; a set of results in the type requested and a status ofREST:SUCCESS - if
return/testis not an operation recogized bySERVICE: returnREST:ERRORif it is completely wrong (e.g. a typo likeretrun/test), orREST:NOT IMPLEMENTEDin case it is planned for later.
4
This distinction is a lot cleaner than mixing the two different things up. It will also make debugging easier and processing only slightly more complex, if at all.
- If an HTTP 404 is returned, the server tells me, “I have no idea what you're talking about”. While the REST portion of my request might be perectly okay, I'm looking for par'Mach in all the wrong places.
- On the other hand, HTTP 200 and REST:ERR tells me I got the service but did something wrong in my request to the service.
- From HTTP 200 and REST:EMPTY, I know that I did nothing wrong – right server, the server found the service, right request to the service – but the search result is empty.
Summary
The problem and discussion arises from the fact that HTTP response codes are being used to denote the state of a service whose results are served by HTTP, or to denote sth. that is not in the scope of the HTTP server itself. Due to this discrepancy, the question cannot be answered and all opinions are subject to a lot of discussion.
The state of a request processed by a service and not the HTTP server REALLY SHOULD NOT (RFC 6919) be given by an HTTP response code. The HTTP code SHOULD (RFC 2119) only contain information the HTTP server can give from its own scope: namely, whether the service was found to process the request or not.
Instead, a different way SHOULD be used to tell a consumer about the state of the request to the service that is actually processing the request. My proposal is to do so via a specific header. Ideally, both the name of the header and its contents follow a standard that makes it easy for consumers to work with theses responses.
回答14:
According to the RFC7231 - page59(https://tools.ietf.org/html/rfc7231#page-59) the definition of 404 status code response is:
6.5.4. 404 Not Found The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists. A 404 status code does not indicate whether this lack of representation is temporary or permanent; the 410 (Gone) status code is preferred over 404 if the origin server knows, presumably through some configurable means, that the condition is likely to be permanent. A 404 response is cacheable by default; i.e., unless otherwise indicated by the method definition or explicit cache controls (see Section 4.2.2 of [RFC7234]).
And the main thing that brings doubts is the definition of resource in the context above. According the same RFC(7231) the definition of resource is:
Resources: The target of an HTTP request is called a "resource". HTTP does not limit the nature of a resource; it merely defines an interface that might be used to interact with resources. Each resource is identified by a Uniform Resource Identifier (URI), as described in Section 2.7 of [RFC7230]. When a client constructs an HTTP/1.1 request message, it sends the target URI in one of various forms, as defined in (Section 5.3 of [RFC7230]). When a request is received, the server reconstructs an effective request URI for the target resource (Section 5.5 of [RFC7230]). One design goal of HTTP is to separate resource identification from request semantics, which is made possible by vesting the request semantics in the request method (Section 4) and a few request-modifying header fields (Section 5). If there is a conflict between the method semantics and any semantic implied by the URI itself, as described in Section 4.2.1, the method semantics take precedence.
So in my understand 404 status code should not be used on successful GET request with empty result.(example: a list with no result for specific filter)
回答15:
Encode the response content with a common enum that allows the client to switch on it and fork logic accordingly. I'm not sure how your client would distinguish the difference between a "data not found" 404 and a "web resource not found" 404? You don;t want someone to browse to userZ/9 and have the client wonder off as if the request was valid but there was no data returned.
回答16:
Why not use 410? It suggests the requested resource no longer exists and the client is expected to never make a request for that resource, in your case users/9.
You can find more details about 410 here: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
回答17:
Such things can be subjective and there are some interesting and various solid arguments on both sides. However [in my opinion] returning a 404 for missing data is not correct. Here's a simplified description to make this clear:
- Request: Can I have some data please?
- Resource (API endpoint): I'll get that request for you, here [sends a response of potential data]
Nothing broke, the endpoint was found, and the table and columns were found so the DB queried and data was "successfully" returned!
Now - whether that "successful response" has data or not does not matter, you asked for a response of "potential" data and that response with "potential" data was fulfilled. Null, empty etc is valid data.
200 just means whatever request we did was successful. I'm requesting data, nothing went wrong with HTTP/REST, and as data (albeit empty) was returned my "request for data" was successful.
Return a 200 and let the requester deal with empty data as each specific scenario warrants it!
Consider this example:
- Request: Query "infractions" table with user ID 1234
- Resource (API endpoint): Returns a response but data is empty
This data being empty is entirely valid. It means that user has no infractions. This is a 200 as it's all valid, as then I can do:
You have no infractions, have a blueberry muffin!
If you deem this a 404 what are you stating? The user's infractions couldn't be found? Now, grammatically that is correct, but it's just not correct in REST world were the success or failure is about the request. The "infraction" data for this user could be found successfully, there are zero infractions - a real number representing a valid state.
[Cheeky note..]
In your title, you're subconsciously agreeing that 200 is the correct response:
What is the proper REST response code for a valid request but an empty data?
Here are some things to consider when choosing which status code to use, regardless of subjectivity and tricky choices:
- Consistency. If you use 404 for "no data" use it every time a response is returning no data.
- Don't use the same status for more than one meaning. If you return 404 when a resource was not found (eg API end point does not exist etc) then don't also use it for no data returned. This just makes dealing with responses a pain.
- Consider the context carefully. What is the "request"? What are you saying you are trying to achieve?
回答18:
404 would be very confusing for any client if you return just because there is no data in response.
For me, Response Code 200 with an empty body is sufficient enough to understand that everything is perfect but there is no data matching the requirements.
回答19:
According to Microsoft: Controller action return types in ASP.NET Core web API, scroll down almost to the bottom, you find the following blurb about 404 relating to an object not found in the database. Here they suggest that a 404 is appropriate for Empty Data.
来源:https://stackoverflow.com/questions/11746894/what-is-the-proper-rest-response-code-for-a-valid-request-but-an-empty-data