11 ms·
REST Anti-Patterns (2008)
- strictnein 9y ago> Ignoring status codes My favorite is when everything returns a 200, but the response is something like: { status: "fail", error: "forbidden" } Sometimes they even include the 403 in the response, almost like the developer is giving you a giant middle finger.
- ferentchak 9y agoYou can blame old browsers for this. In the old days if you returned a non 200 the browser could die in all sorts of interesting ways. Heaven forbid if you try and use any verb other than GET or PUSH, it probably turns the fan off your computer to try and start a fire or something.
- mhluongo 9y agoDo you mean POST? Also, these days, I think the blame is more likely lazy devs, poorly complying frameworks, or compromises to make things easier for some frontend library.
- coldtea 9y ago>You can blame old browsers for this. In the old days if you returned a non 200 the browser could die in all sorts of interesting ways. No, they really didn't. And I've started with Mosaic...
- JustSomeNobody 9y agoWho on Earth is using a browser so old that this might actually happen?
- sratner 9y agoSome of the fault for this lies with client libraries. Many, including popular ones[1], either don't provide a way to get the body of error responses at all, or make it particularly cumbersome to do so. For example, success bodies might be parsed automatically by registering the right parser for the content type, but to parse an error response you need to manually instantiate a parser and deserialise the body. Until error responses are first-class objects in client http libraries, devs will continue being lazy. [1] Not to pick on retrofit -- it is generally awesome -- but http://square.github.io/retrofit/2.x/retrofit/retrofit2/Response.html http://square.github.io/retrofit/2.x/retrofit/retrofit2/Resp...
- vog 9y agoThis was a common workaround, so that customers don't get nervous, as some browsers showed an increasing number in a red circle at the top right. (i.e. the number of JavaScript errors)
- fenwick67 9y agoomg I saw this once. The status code was 200 but the HTTP body was literally "403: Forbidden". On an endpoint that was supposed to return XML . I guess they just read the spec and assumed "the API returns a '403: Forbidden' " meant this.
- themoat 9y agoI wish I only saw this once. This is my life. I integrate with 3rd party APIs for a living...what I've learned is that everyone's 'REST' API is terrible in one way or another.
- boubiyeah 9y agoAll my clients do that. They literally think that REST means "JSON over HTTP" and don't bother with anything else :(
- deleted 9y ago[deleted]
- SomeStupidPoint 9y agoWait... You gotten a response that's HTTP 200, but the JSON itself contained something like "code: 403"? Well, now I know what I'm going to do if I ever really hate my coworkers/company.
- boubiyeah 9y agoI've seen that, and also status = 500 with the body { ok: false, status: 404 }
- strictnein 9y agoThe codebase I'm working on currently has that and more.
- jack9 9y agoThat leads to cleaner code for the frontend frameworks, better interoperability and simpler debugging. Web server error codes are for web server failures and application level errors are communicated via a 200, properly. I run in to this all the time and once we adopted it (for all our APIs), life has been better for customers and our internal teams.
- strictnein 9y ago> "application level errors are communicated via a 200, properly" Wiki: 2xx Success This class of status codes indicates the action requested by the client was received, understood, accepted, and processed successfully RFC 2616: 10.2.1 200 OK The request has succeeded Not really "proper" to use it that way, but if it works for you and your users I guess go for it. Also, I highly disagree with the rest of it (cleaner code, better interoperability, simpler debugging), but those are matters of opinion so there's no point in arguing them.
- jack9 9y ago> client was received, understood, accepted, and processed successfully How is this not processed successfully? The request was processed successfully by the webserver ... and the error was handled by the application, so you can reliably say it was processed successfully at that level, down to the CPU. Narrow interpretation to fit a narrative has no technical merit. That being said, standards are set with certain models in mind and are imperfect almost uniformly, so I don't put too much stock in adherence to what someone imagined or put through committee at some point. I do try to find the best way to iterate reliably with least astonishing abstractions and predictable interfaces. I reason about it in the terms of the standard and it serves my teams.
- VonGallifrey 9y ago> Web server error codes are for web server failures and application level errors are communicated via a 200, properly. I guess google, facebook, microsoft and all the others are doing it wrong then? Or Improperly according to you? Because they do not respond with a 200 on application level errors in their APIs.
- dustingetz 9y agoA quick glance at history of HTTP can explain this without incompetence. HTTP is fundamental to the world wide web and existed from the beginning in 1989. Fielding's dissertation introduced the idea of REST in 2000. And REST became part of mainstream client libraries in what, 2010? So there's a 20 year period during which code was written against HTTP libraries which were not idiomatic from a REST perspective. Returning status codes in the response body is a common workaround for compatibility with code written in this 20 year window.
- boubiyeah 9y agoNor was it even just idiomatic HTTP. Using the proper HTTP status or verbs for instance is not REST, just caring about the HTTP spec.
- dustingetz 9y agoyou're right, a little deeper digging and i learned that in 1989 http only had GET! I dont think verbs came until '96
- strictnein 9y agoI've seen plenty of this is in code written in the past 5 years, some within the last year or two.
- JimDabell 9y agoStatus codes aren't something introduced by REST, they've been a standard part of HTTP since HTTP 1.0. They've been in widespread use for decades. People use 200 for errors for a few reasons, but it's not because HTTP 0.9 didn't have them.
- mattmanser 9y agoI started programming professionaly in 2005 and I can assure you that back then, outside of the browsers, people really didn't know or understand response codes. There's a load of early, popular, Stack Overflow questions that revolve around what status to return when, and how to actually return those codes in your language. For example, in ASP.Net/IIS it was actually quite hard to stop IIS 6 (?) from swallowing your 500 xml response and serving a custom html error page. If I remember correctly some browsers didn't support PUT properly either. So while you are technically correct, the codes were in use, you are historically wrong, few people outside of a small community understood their use. I remember this article from the first time around, when people were really getting into REST and there was a fierce debate about strict REST Vs RESTful. In reality RESTful has mainly won and this article was on the wrong side of history.
- foobarrio 9y agoI remember reading that ISP's and browsers can do interesting things to non-2xx responses. In that case applications do not even have a chance to handle the error. IIRC Facebook's API does this because they encountered problems with mobile browsers deciding to do weird things with non-2xx responses.
- scaryclam 9y agoNo, this hasn't ever been a thing. This is just stupidity on the side of the developers. You may be thinking about DNS hijacking by ISPS, but not non-200 issues. There are bound to be some terrible apps out there that respond badly as well, but that's really no excuse.
- foobarrio 9y agoI am not talking about the app I am talking about the environment the app is running in. Of course there are crappy apps (I've made a bunch of them!) I remember IIS doing funky things with non-200 return codes. 5xx codes would have some default handler. I am certain this was an issue with configuration and a dysfunctional development process. In the shop I was in, in the mid 2000's, we the devs didn't have direct access to the web server and having the IT guys make any update took on the order of weeks. Instead of fixing the IIS config we just returned 2xx and handled the error in the app layer. We also had a couple SOAP(shudder) services that always returned code 200 with error codes in the response XML body. Much of our app code used this pattern for consistency. We also would deploy our services on various other web servers we didn't have full control over so it was just easier to use this pattern.
- lultimouomo 9y agoThis used to be necessary with flash clients, as they wouldn't get the response body if the response had an error status. I can't think of a reason to do something like this nowadays that flash is dead.
- brut 9y agoThis is how GCP tells you access to a resource is forbidden. I wrote an Ansible dynamic inventory script and have had to deal with this behaviour. For example: Response 403 {'error': {'errors': [{'domain': 'global', 'reason': 'forbidden', 'message': "Required 'compute.instances.list' permission for 'projects/golden-sandbox-162219'"}], 'code': 403, 'message': "Required 'compute.instances.list' permission for 'projects/golden-sandbox-162219'"}}
- X-Cubed 9y agoMicrosoft Silverlight (RIP) only exposed 200 and 404 status codes to the application when using the browser's HTTP stack, presumably due to some API limitation somewhere along the line. See the Remarks section: https://msdn.microsoft.com/en-us/library/system.net.httpstatuscode%28v=vs.95%29.aspx?f=255&MSPPError=-2147217396 https://msdn.microsoft.com/en-us/library/system.net.httpstat... Other client plugins may have similar issues.
- throwaway18917 9y agoHave we considered that these REST "anti-patterns" exist because REST is fundamentally inappropriate for what most people are trying to use it for? What if you can't shoehorn your functionality into the handful of REST verbs? What if none of the status codes make sense? What ever happened to plain old RPC? Have we stopped to consider that people tunnel things through POST or GET requests because it's easier and more flexible than trying to cram your functionality into GET, POST, PUT, PATCH, or DELETE? If you find yourself using a lot of these anti-patterns, maybe you should consider switching to something a little less "REST-ful".
- RandomOpinion 9y agoMuch as I would like to agree with you, that war was already fought and lost in the early '00s. Port 80/443 were the two ports that couldn't ever be firewalled because web browsing depended on them, so everybody rushed to cram their RPC requests into some kind of HTTP-based protocol.
- xg15 9y agoHTTP != REST though, as the article notes. There are other ways to use port 80/443 that neither violate HTTP nor go full REST - websocket being an (extreme) example. Even the HTTP monopoly is changing. There are lots of new protocols (HTTP2, QUIC, WebRTC) that work besides firewalls and things like ALPN gives a standardized way to tunnel new protocols over an encrypted connection.
- coldtea 9y ago>HTTP != REST though, as the article notes. The article might note it, and Roy might insist on it, but nobody cares. For all intents and purposes, what people call REST in practical use is RPC over HTTP with JSON responses.
- boubiyeah 9y agoBut then these people are just very wrong. No point encouraging them either :)
- dicroce 9y agoIf API's are best represented via REST, then why aren't software API's in general RESTful (e.g. I dont POST triangles to my GPU)? The answer: SOME API's are best represented with REST, but most are not.
- favorited 9y agoBecause the concept of REST was specifically designed around HTTP, not to be some abstract interface between any 2 systems.
- yeukhon 9y agoI agree but also have counter example, perhaps not yet as an interface for two systems. But let's start with this: What if I can ask my OS to do things I normally do over some protocol like HTTP in a RESTful style? Create user, list directory, find the last login, tell me linux kernel version. ^ has been done as a separate monitoring tool like Osquery, but can't we make such protocol natively? I don't want to parse my command-line output if I can just speak in one human-readble, machine-friendly dialect.
- coldtea 9y ago>What if I can ask my OS to do things I normally do over some protocol like HTTP in a RESTful style? Create user, list directory, find the last login, tell me linux kernel version. The /proc filesystem is somewhat close to that when it comes to GET. >I don't want to parse my command-line output if I can just speak in one human-readble, machine-friendly dialect That's not what REST (the original concept) is about.
- yeukhon 9y agoI understand REST's original motivation, but having a modern protocol to work with resources on a computer doesn't seem too much to ask.
- deleted 9y ago
- marichards 9y agoMissing anti pattern: consider URLs insecure, especially if for a web browser. Don't include customer details (name, email, account number, etc) or search queries (free text) unless you have determined the security settings on your logging, audit, proxies, .., all conform to data protection requirements that suggest they should be encrypted and only visible to necessary staff. If you expect pages to be bookmarked or shared, then consider the security impact of where they are stored on local machines too, including in caches if your company is silly enough not to enforce disk encryption for all users.
- rhizome 9y agodata protection requirements... Link?
- blowski 9y agoPCI DSS is a related example. You can't store credit card data in your logs.
- Sohcahtoa82 9y ago> consider URLs insecure, especially if for a web browser. A web site I used recently puts your session ID in the URL. If you log in, then alter the URL to remove the session ID, you appear logged out. It gets even worse. Clicking the "Log out" button on the page simply removes the session ID from the URL. If you go back and reload the web page with the session ID in it again, you still appear logged in. The page also doesn't use HSTS so is easily vulnerable to SSLStrip.
- LgWoodenBadger 9y agoThis is common in servlet-container-land (Java) for handling browsers that don't support cookies. The URLs are rewritten to include the session-identifier (usually a cookie) as a request parameter instead. There's no other mechanism to associate an HTTP request with back-end state (logged-in/out, etc.) except for session identifiers transmitted by the client browser (through cookies, headers, request parameters).
- yeukhon 9y agoMy #1 complaint is there is no OOP client available from service provider. i.e. building a driver to consume the response and turn that into your client code. The irony is I often write my own harness for REST service, and those are generally object-oriented, because I don't want to speak HTTP over and over. Basically I built my a client while writing test, but I need to write test to assert my client which was developed to help writing my test.
- maxxxxx 9y agoSOAP works that way. But that has its own set of problems...
- daliwali 9y agoThe biggest anti-pattern of all: marketing your API as RESTful, when it is really more RPC-like. I agree on all points of this article. The only nitpick I have is that tunneling through GET/POST is strictly necessary for HTML forms, since they do not support other verbs.
- deathanatos 9y ago> The only nitpick I have is that tunneling through GET/POST is strictly necessary for HTML forms, since they do not support other verbs. Only if you ignore AJAX in its entirety. Yes, the browser's capabilities are limited, as it must be a common denominator and can't describe every situation, and thus, can only GET/POST in certain forms.
- dang 9y agoSame title, different article from a few months ago: https://news.ycombinator.com/item?id=12479370 https://news.ycombinator.com/item?id=12479370.
- saral 9y agoThis provides a very concise and to the point explanation of the original article.
- kbutler 9y agoThe problem is that people want an RPC mechanism, and REST gives them a document transfer mechanism. If your API will never be navigated by a human operating a browser, a lot of the REST specification is inapplicable (navigation links, etc.) So you're throwing out a lot of REST regardless, and the question becomes where to draw the line between ease of implementation and compliance with a standard that doesn't really fit your needs.
- wtbob 9y agoAnother problem is that people want an RPC mechanism, when what they need is a state-transfer mechanism. It turns out that the semantics of RPC — attractive as they undeniably are — are pretty poor for building real-world distributed systems, while those of REST as a pretty good (or at least better) fit.
- throwaway55523 9y agoPeople need both. REST works well for CRUD operations that don't have complex side effects or constraints. What's often missing in this is intent. I just want to do "the thing" to this particular account or whatever. Personally I like to very selectively add RPC actions on top of the base resource. Tacking an RPC action onto the resource URI allows you to encapsulate the intent of the user's action, handle all the updates required server side, and then return the updated representation.
- boubiyeah 9y agoI almost always have both. I tend to use event sourcing and the intent is mandatory. There might be 20 reasons to modify one resource, each with its own list of side effects to later perform. So it's usually POST resource/:id/action and that's fine.
- naasking 9y ago> So it's usually POST resource/:id/action and that's fine. There's nothing wrong with that. It's not anti-REST or anything, assuming you satisfy the other REST constraints, ie. each request is self-contained and any stateful resources are designated by URLs. As an aside, I'm personally not a huge fan of human-readable URLs because it encourages API consumers to rely on/construct URLs client-side, which is not REST.
- sopooneo 9y agoI believe REST as Fielding defined it has some great benefits. But I'm not a purist. And actually, neither is the person who wrote this post. Because no matter how much the disciples try to wriggle there way around it, using cookies for sessions is not allowed. "We next add a constraint to the client-server interaction: communication must be stateless in nature, as in the client-stateless-server (CSS) style of Section 3.4.3 (Figure 5-3), such that each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server.Session state is therefore kept entirely on the client." - from Fieldings dissertation. To be fully compliant you have to do use something like HTTP Basic Auth, where you resend the username and password with each request. I think you should use cookies to store a token that the server can then use to determine whether the "context" of the request is "logged in" or not. I do it. But it's technically a violation.
- virmundi 9y agoI question that idea. Cookie is a standard header. So is Authorization. It's up to the server to require either. Basic auth header removes the need for a handshake to negotiate tokens. Authorization: Bearer (token) is now a standard. I suppose Cookie: (token) could be too, but too many people felt dirty. My point is that Cookie does provide the credentials required for the call contex, this fulfilling the self containment requirement.
- sopooneo 9y agoAs I read it, the problem is not the mechanism by which a session is maintained, but the very existence of a session at all.
- jaequery 9y agoseriously i dont really care whether an api is restful or restish. at the end of the day its all the same to me. just give me an api endpoint, request and response objects nicely documented and i am golden.
- lloydjatkinson 9y agoAnti-pattern #1: Using REST. It's just cargo cult along with everyone describing it and then implementing it differently. The only good part it has is how to layout the URL, and even then it's just common sense.
- chazu 9y agoOne can't really fault REST for the flawed implementations - Fielding's thesis is very explicit about what REST is and isn't. Just because something becomes an often-misapplied buzzword doesn't say anything negative about the original concept so much as the people mis-implementing it.