views:

329

answers:

8

i'm constructing a web-service that is used, in this particular case, to ask for information about a patron.

Let's say, for the sake of argument, that the lookup web hit is:

GET /patrons/619 HTTP/1.1

If the patron is found, i return code 200:

HTTP/1.1 200 OK

If you omit, or give an account number that is not a number, i return 400. For example the following bad requests:

GET /patrons HTTP/1.1
GET /patrons/ HTTP/1.1
GET /patrons/G619 HTTP/1.1
GET /patrons/kirsten%20guyer HTTP/1.1

all return error 400 (Bad Request), e.g.:

HTTP/1.1 400 Invalid patron number


i want to have a status code for patron not found, returned as the HTTP status code. For example:

GET /patrons/1322 HTTP/1.1

HTTP/1.1 404 Not Found

i've thought about using 404 (Not Found), which is a valid response (the requested resource was, really and truely, not found.) But i'm afraid people debugging it might think that it means that they spelled /patrons/ wrong.

Can anyone think of another http status code i could use?


Update: i'm eyeballing

204 No Content 
The server successfully processed the request, but is not returning any content.

What say you?


Don't forget, that not all HTTP servers serve up HTML content. If an IIS web-server is asked for a resource called:

GET /MyStartPage.html HTTP/1.1

Then the HTTP server has to decide what to respond with. On most web-servers, a resource named /MyStartPage.html corresponds to a file sitting on the hard drive.

Whereas StackOverflow does:

GET /posts/1027301 HTTP/1.1

Which, if that resource doesn't exist, the web-server should (rightly) return 404.

+5  A: 

IMHO, the HTTP response is not the proper place to handle this, as the error is not at the HTTP level. It's at the application level. One possible solution is to use the Null Object Pattern to return a null 'Patron' that conforms to the Patron interface, but indicates that no such person exists.


UPDATE: I've been convinced that this answer is wrong. However, I want to leave it up, as it is a potentially valid answer (depending on details not presented in the question), and I think the comments are instructive.

Harper Shelby
Agreed with this. HTTP status codes aren't exactly the place to describe events for humans to interpret.
Ian Elliott
What makes you think humans will be interpreting this?
Ian Boyd
+1 Exact to the core.
blntechie
Well, what's an HTTP level error? Are you equating a the server not being able to find a handler for a particular path as the only valid use of 404? That's not the way the protocol spec was designed. The error codes give a meaningful way to classify errors for applications as well.
altCognito
Agreed. It's the application returning the error, not the server. Therefore, a series of error codes should be implemented at the application level.
TFM
I disagree. HTTP is designed to be Application layer protocol. It is a generic one, but the status codes are definitely meant to carry meaning. It is often mis-used as a transport layer protocol in that all status/error information is embedded in the content and thus inaccessible to the HTTP client. But that doesn't change the fact that it *does* provide a way to transport those kinds of problems.
Joachim Sauer
+15  A: 

404 Not Found is the correct thing to return, if it's a service, it's not really being used by humans but by machines, and therefore, typos, shouldn't be your first concern.

Also, there's very little you're going to be able to do to counter human behavior anyway (thinking one thing when it's really another). If you're returning a little error msg as part of the error code, everything should work out. You could even suggest to them a possible fix.

Returning a 500 when the application is doing exactly what it's designed to do also seems a little odd. 404 describes exactly the situation: Resource not found.

altCognito
i'll give the post a few more hours to get others a chance to speak up, but i'm liking your answer. And your elaborations on other errors
Ian Boyd
+2  A: 

Typically if your service encounters an error that it is unable to handle, but the request is well formed, then I would think you would want to return a 500 status code.

Also, another reason why I say 500 would be appropriate is that from my experience in .NET web services, whenever I throw an exception across the wire (such as a RecordNotFound exception), the web server and client have always interpretted the response to be a 500 status code.

Either way, it would be a good idea to review this list of http status codes, and fine the one that suites your needs the best.

Joseph
It is correct for your web server to consider a thrown exception as a 500 error, but it would be more appropriate for your web service code that is throwing the exception to, instead, direct the server to return a 404 response.
Dustin Fineout
@Dustin Not if you intend for your client to consume the exception. If you direct the server to return a 404 response, how does the client consume the exception? I'm not an expert in http responses, so I'm legitimately asking because I'm unsure. What I do know is that if I intend for my client to consume my exceptions, then by default (and I'm not aware this is configureable) the server is going to respond with a 500 code. This is my experience with .NET web services.
Joseph
I'm going to direct you to the answer posted by Andreas, which explains this fairly well. This has nothing to do with .NET, it is a client-server request/response (HTTP) issue. I would not throw an exception in my application in such a case, I would either send response header 404 or send 200 with a content message describing the error. Throwing an exception should indicate there is something wrong within the application code, and then appropriately 500 server error would be the response.
Dustin Fineout
@Dustin I can understand the argument that is made. However, in this case I don't view the error being on the client side. Sure, the client is making the request to a patron that no longer exists, but why? For instance, what if the patron was deleted by some other user and that is why the client in question had requested a user that doesn't exist? Is that not a problem at the server level and NOT the client? I think the true answer here is going to be based on context of your application and how it's used.
Joseph
This has nothing to do with the client, it's all about how you choose to handle it on the server side - you are simply deciding what to *tell* the client. I wouldn't call it the server "level" though, it is clearly something discovered server-side at the application level (what is the "server level"?). HTTP is designed to operate at the application layer. It is correct for the web server to return 500 if the application throws an exception (by definition of the code and what an exception is). But, I wouldn't *in the application* throw an exception. I would send status 404, appropriately.
Dustin Fineout
+5  A: 

Error 404 is actually a more acceptable response for this case, because the resource truly is not found. You could always have a custom error document that explains that it is the Patron ID that is not found.

A 400 error implies that the client sent malformed syntax, which is not the case in your example. Thus, you should not use this error code. It may seem that "Bad Request" is accurate, but what this actually means is there's an error in the request header syntax.

This is also not a 500 error because no error has occurred. There is no problem with the web server fulfilling the request, the fact is that the request is seeking a resource that is not present.

404 is the only appropriate response, unless you want to consider it a fully valid request, return status 200 and a page explaining that the requested Patron does not exist.

Dustin Fineout
+1 for why 200 -might- be good, instead of saying "Yes, send 200 with error code".
maxwellb
+6  A: 

I think you should use 404. Developers of the API will understand what 404 means and will therefore follow there own usual debugging process in order to resolve the problem. Stick to the protocol.

JamesC
A: 

Errors at the web service level should not just return a simple HTTP status line, but should instead return content in a valid and documented format that can be parsed by the client accessing your service. The returned document should contain an error code that is part of a documented set of codes specific to your web service, as well as a short description of the problem and optionally a more detailed description of the problem.

Lars Haugseth
A: 

It depends on which kind of webservice you're constructing.

SOAP and XML webservices typically return 200 OK if a requested object (patron) cannot be found and encode the error type/message/description into the response document. They separate a transport level (HTTP) from the messages exchanged (XML). A 404 error (which is on the transport level) is returned only, if you request a non-existing API endpoint (wrong URL).

With a REST webservice however, you use HTTP methods and statuses directly for message exchange. REST uses different HTTP methods (GET/POST/PUT/DELETE) to specify which action is wanted and the server returns the status as the HTTP status. So in case of a REST webservice, 404 would be the proper HTTP status if a patron could not be found.

500 is inappropriate in any case I think, since 5xx means that there's been something wrong on the serverside (which isn't the case) while 4xx errors mean that there's something wrong on the client side.

Andreas
A: 

If you want to control the web service's responses via HTTP response codes, then you could indeed use a 404 to indicate this condition.

However, I would think it's more natural to have the web service's response defined entirely in the body of the HTTP response, and just return 200 for a successful communication ("I understood your request and have sent you an appropriate response"). In this case then, you'd return 200 as normal with the payload of your request (XML or JSON or whatever) indicating that no matching entity was found

I'd consider non-200 error codes similar to exceptions in conventional programming languages, and the HTTP response body more like the return code. Imagine if you were implementing this conventionally - would you throw an exception if no entity was found, or return null? Personally, given the fragile nature of network connections, I would want to reserve all HTTP-level error codes for problems in communication, and I'd much rather always return 200 OK from the service itself, along with a payload specifying the result or any service-level error.

Andrzej Doyle