11 ms·
Choosing an HTTP Status Code
- mnot 11y agoNot bad. The ordering of 4xx status codes isn't that deterministic (often, it's situational), and last time I checked, Twitter uses 429 instead of 420 now (they like standards).
- Asmod4n 11y agoI can only recommend webmachine here, https://raw.githubusercontent.com/webmachine/webmachine.github.io/master/images/http-headers-status-v3.png https://raw.githubusercontent.com/webmachine/webmachine.gith.... (it starts at b14) This is actual code drawn out as a state diagram. It's officially available for Erlang and Ruby. (Disclaimer: I am one of the "maintainers" of the Ruby version)
- cursork 11y agoSee also Liberator for Clojure
- platz 11y agoSee also Airship for Haskell
- jalfresi 11y agoThe more up to date version of this diagram is here: https://github.com/for-GET/http-decision-diagram https://github.com/for-GET/http-decision-diagram
- Intermernet 11y agoStill Missing: Are you a Teapot? Yes: Error 418.
- andreineculau 11y agosubmit a pull-request :)
- Intermernet 11y agoUnfortunately they don't claim to conform to RFC 2324. If they did, I would :-)
- andreineculau 11y agoIt's good to see more diagrams/flowcharts on the matter, but beyond that - for those that understand the power of abstraction between layers, but you think there should be a simple straightforward to spit out the correct http status code while you worry about the semantics alone: https://github.com/for-GET/http-decision-diagram https://github.com/for-GET/http-decision-diagram * an old PoC in NodeJS exists that reads the states/transitions from a JSON file and calls the correct callbacks in the correct order. Implement the callbacks (semantics) and you're done. Disclaimer: I'm the author.
- ungrim97 11y agoThe for get http repo already looks to provide a http status flow diagram at https://github.com/for-GET/http-decision-diagram https://github.com/for-GET/http-decision-diagram. Its a version 4 currently
- peteretep 11y ago> I’m not completely sure they do matter. > There’s a lot of smart people at Facebook and they > built an API that only ever returns 200. This is the best bit of the article. Most (many?) APIs, whether or not their authors call them REST, are single URL APIs that you throw JSON/YAML/whatever at. If the caller is going to get back a serialized status message (["Not found"]), then the HTTP request was successful, and it should return 200. I'm not sure why people insist on spreading their APIs out between the transport and content layer.
- parent5446 11y agoIf the API is indeed RESTful, and it complies with the concept that a URI represents an address of a specific resource, then returning 200 even when the resource was not found does not make any sense. The request was not "successful", rather the request failed to find what it was looking for! That said, "single URL APIs that you throw JSON/YAML/whatever at" are not RESTful anyway. For a non-REST API, then it may make sense to return 200 even if something was not found, but it is still not a good idea to just ignore the properties of the upper-level protocol your data is ferried on. > I'm not sure why people insist on spreading their APIs out between the transport and content layer. HTTP is not the transport layer. It's an application protocol meant to convey application data. People spread their API over it because that's how it's supposed to be used. If you're just using HTTP as a means to toss random data between computers, you should consider TCP.
- nulltype 11y agoMaybe you should use TCP instead of HTTP, but there's a number of reasons to use HTTP as basically TCP: * Browsers can't speak TCP natively (oddly enough) * HTTP works through proxies * Most web frameworks do HTTP more easily, same for web servers Of course, the real solution here is probably to use websockets or HTTP/2, since then you get all the advantages of HTTP without the downsides of TCP.
- pdkl95 11y ago> (oddly enough) That's by design - allowing arbitrary TCP in a browser is just asking for security and DDoS problems. > HTTP works through proxies So does TCP (SOCKS). > Web servers Using web server wouldn't make sense if you were using straight TCP. The real reasons HTTP is used when plain TCP would be more appropriate are: 1) Lazy/stupid firewalls configured to only allow port 80/443. This leads to everyone doing everything over HTTP, moving the problem and making the firewall much less useful. 2) NAT. When the primary benefit of the internet - where each peer is equivalent in the protocol - cannot be counted on, centralized servers (usually using HTTP because of #1) are used instead of direct TCP.
- parent5446 11y agoSome things I don't particularly like in this diagram: * I don't consider 307 and 308 to be irrelevant. Even if many browsers today are safe against method-change attacks, it's always better to be explicit. * I don't see why 304 would only be used if "implementing a web server". Many web applications do their own Last-Modified or E-Tag checking behind the web server (and for good reason). * There are also non-webserver reasons you'd use 408 and 413. Also > I don’t find this argument compelling, if for no other > reason than this: in a world where everyone is moving > to HTTPS, we’ve forbidden any proxy or caching nodes > that are not under direct control of the server. What? Even if you are controlling the cache, I don't see why you would want to make your job more difficult by having to explicitly control it when HTTP can do much of the job for you. (Not to mention there are cases, specifically AWS and cloud services, where you wouldn't have direct control of your proxy cache, but are still using HTTPS.) Otherwise I'm glad to see some people still think using a variety of HTTP status codes appropriately is a good idea. It makes services easier to use and more intuitive.
- fanf2 11y agoAlso, permanent redirects need a big caveat: if you screw them up you will have a bad day, because they are nearly impossible to fix - browsers take "permanent" literally. Better to use temporary redirects with sensible but limited lifetime.
- spacecowboy_lon 11y agowhy if you stuff up a 301 you just implement a new set - search engines ignore 302's
- nitrogen 11y agoBrowsers can cache a 301
- spacecowboy_lon 11y agoDon't get clever and use these wacky non standard status codes like 307 308 303 your at the mercy of Google as to how they will treat them. 99.9% of the time use a 301 redirect.
- latenightcoding 11y agoBRB adding 418 I'm a teapot status code to all my web apps
- bespoke_engnr 11y agoI actually did this in an app a few years ago, and completely forgot about it for a while. I only remembered when another dev sent a surprised e-mail. Ya gotta make time for fun...
- rix0r 11y agoI hate that "Too Many Requests", or "Throttled", or what have you, is a 4xx status code. It renders simple middleware logic like "retry on a 5xx, don't retry on a 4xx" invalid. If you'd call it "Server Over Capacity" you could just as well argue for a 5xx code.
- vbezhenar 11y agoUsually "Throttled" response carries some information when you can retry. So simple middleware logic to retry with some generic timeout shouldn't be used, instead the response must be analyzed to find out the exact timeout. Probably it's a thin line between client problem and server problem.
- jalfresi 11y agoI'm not sure I follow. The client would receive those errors because they are errors on the clients side; the client should ensure that they are not flooding a service other wise the server will cut them off. Your simple middleware logic is going to have to examine the 400 error in more detail in order to adjust its request rate e.g. exponential back off. It's not that the "server is over capacity", its that the specific client is making "too many requests".
- PeterHorne 11y ago503 = Service unavailable (temporary overload / maintenance) 429 = Too many requests (rate limited)
- electroly 11y ago"429 Too Many Requests" means YOU made too many requests. Retrying will only make it worse. Sounds right to me. You should definitely not simply retry on a 429 response.
- cel1ne 11y agoSlightly off-topic, but I found this article useful when implementing a REST-API: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api http://www.vinaysahni.com/best-practices-for-a-pragmatic-res... It has a section about status-codes: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#http-status http://www.vinaysahni.com/best-practices-for-a-pragmatic-res...
- daurnimator 11y agoUseful resource for status codes: https://httpstatuses.com/ https://httpstatuses.com/ which I always remember better as http://httpstatus.es/ http://httpstatus.es/ More humourous alternative: http://httpstatusdogs.com/ http://httpstatusdogs.com/
- ekimekim 11y agoAlso https://http.cat https://http.cat, my favourite for being shortest to type.
- andreineculau 11y agoAlternative counterparts, based on know-your-http-well[1] : * http://bin.hyperrest.com/ http://bin.hyperrest.com/ * http://httpflies.com/ http://httpflies.com/ [1]: https://github.com/for-GET/know-your-http-well https://github.com/for-GET/know-your-http-well
- jalfresi 11y agoI seem to recall that this flow chart covered all the bases pretty thoroughly: https://github.com/for-GET/http-decision-diagram https://github.com/for-GET/http-decision-diagram
- blowski 11y agoWhat code should I use when a user submits an invalid value over a form? Most of the time, I see 400 or 422, or even 403. I've also seen people say it should be 200, because the HTTP request was successfully handled. It seems like such a common requirement, I'm surprised there's no agreed standard.
- mstade 11y ago400 as far as I understand it is about the request syntax itself. If the error is in semantics (i.e. POSTing a phone number where you expected a date of birth) then the request itself isn't malformed. 403 might be appropriate, but generally concerns authorization more than the ability to process the request -- i.e. trying to POST something the user doesn't have authority to modify would return a 403. If the user is authorized for the specific request, and the request is valid syntactically, but the semantics of the request body makes no sense, then the entity of the request can't be processed and 422 is what you should return.
- blowski 11y agoThank you, I have been using 400, but you're reasoning here makes sense.
- ColinWright 11y agoSee also: HTTP flow chart ready to print [pdf] https://news.ycombinator.com/item?id=10695467 https://news.ycombinator.com/item?id=10695467
- Sujan 11y agoThat's gold: "Are you rage-quitting the internet? ---Yes---> 410 Gone"
- mstade 11y ago> Coda: On Why Status Codes Matter > I’m not completely sure they do matter. > There’s a lot of smart people at Facebook and they built an API that only ever returns 200. https://xkcd.com/927/ https://xkcd.com/927/
- buro9 11y agoThe legacy of JSONP
- rplnt 11y agoI really love Atlassian APIs. JSON request gone wrong? Here you have an error in XML! But I geuss that's expected when your documentation only has XML examples. What about a request for non-existing resource (a file)? That's a 200 OK with an HTML for you! Also, the content of the HTML is "<h1>200 OK</h1>". Luckily most of the functionality in their products is not implemented through the APIs...
- fluxquanta 11y ago>I really love Atlassian APIs. JSON request gone wrong? Here you have an error in XML! There's a company I work with that is similar to this: Requests are XML, successful responses are returned as JSON with status 200 (with an empty error status field), errors are returned as XML with status 200, and the error text node is always "An error occured [sic] with your request".
- TheAndruu 11y agoHard to get behind an argument on status codes being pointless when the article itself cites the usefulness of wisely chosen status codes, such as "201 Created, 429 Too Many Requests, and 503 Service Unavilable". I've created and used many a RESTful API and can vouch the ones that just return 200 even in cases of error are a big pain in the neck. This is usually done (IMO) as a shortcut on the hand of the service provider, lack of knowledge on the conventional codes that should be used, or for the sake of more flexibility when endpoints change. However, all of those reasons just push more work onto the service consumers. Lack of standardized status codes means the consumer must have customized error detection, which is more susceptible to changes as the provider pushes out updates.
- nitrogen 11y agoI've seen APIs that always return 200 because the iOS app that was the API consumer couldn't handle non-200 responses (something about it being harder to get the response body IIRC).
- oxguy3 11y agoDunno bout iOS but I know Java's built-in HTTP library requires you do something like `if (status<400) { stream = getResponseStream() } else { stream = getErrorStream()}`. It's so silly.
- paulddraper 11y agoYeah, Java's HTTP stuff is barely usable. If you are doing more then playing around, use singing better. Apache httpclient is a very well constructed library. And there are bunch of other smaller ones.
- anExcitedBeast 11y agoHTTP status codes are also useful for infosec people during breach investigations. Sometimes all that's available is access logs, and those codes can provide a lot of context.
- IshKebab 11y agoRather than saying what error code I should or shouldn't use because of an out-dated loosely followed spec, maybe tell me based on what modern browsers do.
- rickycook 11y agowell browsers are frequently not the important interfaces to an api (other than the 3xx)
- Cakez0r 11y agoWhat if you need to communicate an error reason with your status code? E.G. distinguishing between Forbidden because you don't have some permission and forbidden because you're not friends with some user.
- Rezo 11y agoI like to return a error code property for each particular error case in the JSON body of the response. This allows you to determine exactly where in the code the error is from, and also allows the client to do fine-grained error handling in the UI if required. I've also found it incredibly useful to include a unique error ID with each request that is also logged server side, so that you can pinpoint the request in your logs and look up the context including previous and next requests. It looks something like this: HTTP 403 { errorCode: 403102, message: "Missing required permission: IN_SOCIAL_NETWORK", id: "064d6a1f-ba30-47de-8975-c319f01729ca" }
- nkassis 11y agoCan you just add the reason in the response? Don't need a super specific error code for this. Could also be a 400 since users should not be asking for information on people they are not friends with, that seems like something is wrong with the request.
- enobrev 11y ago"the existing status codes are much too general for a modern website/API... why worry about spending any time on a redundant, not-as-useful HTTP status code? When pressed for a reason why it is important to use specific status codes, a common reason cited is that HTTP is a layered system and that any proxy, cache, or HTTP library sitting between the client and server will work better when the response code is meaningful. I don’t find this argument compelling, if for no other reason than this: in a world where everyone is moving to HTTPS, we’ve forbidden any proxy or caching nodes that are not under direct control of the server." I do find this reasoning to be perfectly valid and have implemented many APIs accordingly for quite some time. It has a lot to do with the first place to look when something goes wrong. Does the 404 mean I mistyped the URL or that the Application can't find the Resource? Did the endpoint crash or did I mess up the rewrite in the nginx config? That said, Michael's counter-argument is well worth consideration. I've generally left HTTP status codes and Application status codes completely separate for any sizable project, but I find this article and argument worthwhile and will continue to reconsider, as I generally do upon every new project, whether using HTTP status codes to represent general application state is worthwhile. The original point regarding complexity is most important to me, but Michael's diagrams do an excellent job of showing how Application state can be considered an extension of the Protocol in specific cases.
- lukiebriner 11y agoI agree with parent5446 - there are various codes that although they are usually only used by web servers, they are also used in some REST APIs, including mine. e.g. I return 304 when people query an image 1) Because it is not a static resource but is pulled in from another server and 2) It will never expire because if it changed, a parameter in the URL would also change.
- virmundi 11y agoI've been down in the weeds a bit when it comes to authorization. Every resource in my system has its group information in an attribute {:rights {:c [..list of groups], :r [..] :u [..] :d [..]} ....rest of resource...}. In parallel with the resource as above, there is an index table for all of the resources in the system. When a resource, our group of resources is queried, I filter the index table with the groups for the current user and join to the resource table. I can only bring back resources for which the user has rights for the operation. This means that I can't ever have a 403. All I can return is a 401 or 404 or a 200 with an empty list. I kept fretting about this. Now I feel better. #how-i-stopped-worrying-and-learned-to-love-the-atomic-codes.
- aaronbasssett 11y agoIn general terms: * 2xx - We've got it! * 3xx - They've got it * 4xx - You fucked up * 5xx - We fucked up
- jstimpfle 11y agoSome 4xx are "you fucked up", but I would say more of them are "sorry, not possible" or "sorry, transaction failed".
- ap22213 11y agoAn API is an interface. Like all interfaces, an API has an 'audience'. Generally, the successful team will try to make their interface as usable as possible to that 'audience' (considering diminishing returns).
- cletus 11y agoSome of the comments here are positing a false dichotomy. The choices aren't between returning 200 with an error code and returning an HTTP code for each error. I've gone down the path of trying to shoe horn every error condition into a separate HTTP status code and (IMHO) it's a Big Mistake [tm]. You really are confusing transport and application layers and the transport layer simply doesn't have enough codes for what you need. When something obviously fits into an HTTP status code then sure, use it, particularly when it'll mostly make your client do something sensible. But you just can't get away from needing error codes that go beyond HTTP status codes for any moderately complex Web application.
- mkobit 11y agoThis is the first time I have really noticed the '405 Method Not Allowed' code. This makes it seem like you should explicitly handle every verb, when in cases before I have just left them unimplemented (which typically just results in a 400). Is it considered a best practice to handle all of these other verbs with a '405'?
- wylee 11y agoI personally think it's best practice, although returning a generic 400 isn't _that_ bad. Libraries like Django REST Framework handle this automatically.
- joveian 11y agoAfter looking at magic getopt yesterday I noticed Colin Percival's "The HTTP 500 Soltion" article: http://www.daemonology.net/blog/2015-11-27-the-HTTP-500-solution.html http://www.daemonology.net/blog/2015-11-27-the-HTTP-500-solu... I tend to agree with that and even more so looking at these flow charts. Complex error handling is an easy source of bugs. At the very least, return codes should be limited to the minimum information needed to prompt the desired action in browsers, proxies, and search engines.
- myth_buster 11y ago4XX response > Is the user being throttled? > Are you Twitter? > 420 Enhance your calm. A weed reference?
- 3pt14159 11y agoEdit: This comment comes off as overly critical. I really do love these diagrams, I've just had this argument so many times with people I find it frustrating. I completely disagree with this part of the diagram: https://imgur.com/HZS3cVy https://imgur.com/HZS3cVy If the resource is secret then the entire guessable path should return a 401 or a 403, not a 404. Knowing whether something exists is a privilege that a user needs to authenticate in order to gain. This isn't just an academic distinction. Github does 404s for unauthenticated requests and python's default http client (at least for python 2) doesn't send credentials unless it hits a 403 or a 401. Since github sends a 404 you have to hack around the language. 404 means Not Found. But that isn't true. The real status code is Forbidden and it should be used on all possible urls that follow a guessable pattern.
- mjpuser 11y agoI think that you have a point as far as staying true to what the status codes mean, but it comes with a price. To make the resource invisible to the user by 404ing instead of 403ing, you protect yourself from people searching for endpoints that return personal info... and all urls are guessable. If you get a hit on some resource in a sea of 404s, you are that much closer to gaining private info.
- 3pt14159 11y agoBut if there is a chance that a resource exists at all, then that whole range of URLs should return 403, regardless of whether or not they exist.
- deleted 11y ago[deleted]
- Walkman 11y agoSometimes 403 give away information (The resource you tried to reach exists) which you don't want to give away at all because it's much secure.
- 3pt14159 11y ago
- MichaelGG 11y ago>Postel's law states that one should be conservative in what one does, but liberal in what one accepts from others; this is great advice for life, but terrible advice for writing software. This perfectly sums up what I've tried to say about this "robustness principle" for years. Fantastic. SIP inherits these status code ideas, plus adds super-neato whiz-bang headers, like "Retry-After", that allow comments. Their actual example is "Retry-After: 300 (in a meeting)". It's beyond delusional. Except.... someone read the spec. They see Retry-After. They then implement it in some big iron that connects to the PSTN. Little SIP VoIP provider comes along, passes along this dumb header, Retry-After. Suddenly, big switch guy is pissed, as Verizon has disabled all his lines as "Retry-After" gets translated into "shutdown trunk" or something. Awesome. Really a round of applause for the IETF there. (You have got to know that these headers came about just sitting around thinking shit up, vs actually trying to implement telephony. That's why SIP says it might be used "to run a chess game", but has a mandatory "Call-ID" field. Oops.)
- justizin 11y agoAnyone who thinks 304 Not-Modified is mostly-irrelevant in 2015 is mostly-irrelevant.
- victorbojica 11y agoIt's not that shocking that this news has made it to the top here. It is very difficult to choose the right code, tough it might sound simple...