- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Please stop using the term "RESTful" to describe JSON-over-HTTP APIs. It doesn't apply to APIs. See https://unixdigest.com/articles/no-your-api-isnt-rest-but-dont-worry-it-really-shouldnt-be.html
Admin
HATEOAS is there for a reason
Admin
It's not actually just a matter of "preference" here, the one way is objectively wrong.
This looks like a Problem Details JSON Object. ASP.NET Core for example generates this by default when you return a "BadRequest", it's supposed to take an
IDictionary<String,String[]>
with the idea being you can have multiple errors for the same field.I agree that systems which always return a 200 response with an "envelope" for the result is terrible, but RFC9457 is as close as we've got to a standard way to return structured errors to clients. If clients receive any kind of non-success status code, this provides a "standard" structured way for them to inspect the error from server, the fact that it duplicates the response code is redundant, but it is also convenient for consumers and is also "nice" when you're testing an endpoint in something like Swagger UI.
Admin
I'm not well versed in web development but in my mind, returning http error codes is a backend development thing (handling them on the other hand)…
Admin
I don't see how that breaks REST. Returning an error code is returning an error code. It's still part of the message. How does that drive you insane?
Admin
My team just inherited the maintenance responsibility for a REST-ish API with a substantial misfeature.
If the API handler receives an endpoint it doesn't know about, one would normally expect to get a 404 back, but this one is a little ... special. If you are authenticated, you get back a 401, while if not, you get back a 403. This caused fun and games, since the application that interrogates the API cannot use a 404 to detect that it's talking to an old version of the API that doesn't have the new endpoint.
At least it's not a 418...
Admin
There is a good bit of debate [has been for years, and not limited to ReST or JSON] about how to handle "single" items when it is conceptually possible that there could be multiple..... The majority go with "always use an array" [perhaps even including an empty array for when there are no elements. But there is a group with decays single element arrays to values [and zero elements, to elimination of the key entirely, in JSON]...
Admin
In trying to map all the various 400 and 500 codes into something meaningful, I finally gave up and returned a 200 with the data structure containing a text description of the actual problem and instructions for the user to resolve. This is an an internal app and that would be an anti-pattern for the traditional E-Commerce app.
Admin
Is "orderSatus" a typo in the code or only this article/submission ?
Admin
On the client side, I've worked with a platform that's supposed to act as a client to any REST service, but only exposes any information about the response body if the status code indicates success. For a 4XX or 5XX response, the body isn't captured or logged anywhere. All we know is that something failed. If the normally expected response is a JSON array, then the response code isn't exposed, so there's no way to tell whether the service successfully returned an empty array or it returned an error.
Admin
That is in the original code.
Admin
There is nothing whatsoever stopping you from returning both a different error code and a structured message with more info about the error. This way you get the best of both worlds.
Admin
Ehm, I'm not sure how not doing proper error reporting helps with proper error handling. When people just 200 instead of using one of the only few error code available, it's just sloppy.
Admin
So the issue is that those HTTP error codes have actual meaning within the protocol itself. And when they get returned for whatever arbitrary reason some random developer wants to use it makes things worse not better. Especially since most of the time just the status code isn't meaningful anyways without interrogating the actual response.
Admin
I wholeheartedly agree with you here. REST is an architectural style for distributed hypermedia systems, like the World Wide Web. If you do not implement a WWW-like system, you should refrain from using REST. Fielding himself wrote this to his dissertation: "The REST interface is designed to be efficient for large-grain hypermedia data transfer, optimizing for the common case of the Web, but resulting in an interface that is not optimal for other forms of architectural interaction.". So, no WWW-like system? Don't use REST!
The main beauty of 'real REST' IMHO lies in that you can make massive changes to a system without bothering your clients to update their software. You can add or remove servers from the web, add proxies, add pages, delete pages, totally change existing pages. And all of that requires no new browser: you can use all of the changed functionality without a client software update. Massive change: no new software needed to work with the change. That is simply not the case with Overloaded-HTTP-returning-JSON-api's. Any change needs new client-side software to be able to use that change. And no: ignoring new fields is not equal to 'using that change'.
I cannot stress this enough: REST is about NOT having to change client software. (Within certain limits of having to download a new browser every now and then, to get the latest and greatest rendering of html-tags.) If you need new software to be able to use the newest Overloaded-HTTP-returning-JSON-api calls, that API is totally outside the spirit of REST. Stop calling it rest and read https://ics.uci.edu/~fielding/pubs/dissertation/top.htm.
Admin
One of the problems is, perhaps, that there are two kinds of errors:
"Soft" errors, where the error is in the handling of the specific request. (Ex: a request to delete a non-submitted order that arrives just after the automatic deletion nukes it.)
"Hard" errors, where the error is that the system wasn't even able to try handling it. (Ex: the server receives the request, but when trying to parse it, fails hard due to an out-of-memory condition or an off-line request to a service that immediately crashes. Ex: the client submits a request to an endpoint that doesn't exist.)
It's not hard to justify saying that "hard" errors should be indicated by 4XX/5XX error codes on the HTTP header, and I suspect that most people would agree. The real debate is about "soft" errors - are they sufficiently "errorish" to merit an HTTP error versus a 200 with the "true" error code in the response body? If they can be 200ed, where do you draw the hard/soft boundary? Is an authentication failure a hard error or a soft error? (I'd say "hard", but...)
Admin
I disagree, your "soft" example is a clear 410 (Gone). There is no soft error; there's various versions of 2xx codes, so there can be soft successes but errors are always absolute.
Admin
If the API is able to generate and send a response then from the HTTP perspective it was a success, which is all a 200 response code is supposed to tell you.
Admin
A true REST request/response is usable entirely within the contents of the message itself independent of how that message is transmitted. So it should be possible to send REST over HTTP, or FTP, or Fax or carrier pigeon. Obviously that's not possible if the service relies on HTTP specific error codes not contained in the actual message body.
Admin
Fair point. Perhaps "hard" and "soft" weren't quite the right terms. Perhaps "system" ("hard" or "request cannot even be attempted") and "application" ("soft", "request could be attempted, but didn't work out") errors are better terms.
Addendum 2024-06-24 13:42: But I did say there's a question to be debated, not that it's OK to present "soft" errors as a kind of failed success. (For what it's worth, I'm mostly on the side of "an error is an error, the end". Sorry for having not made that clear.)
Admin
I kind of get what you are saying but your specific example is not a soft error. In REST terms, to delete an order, which is presumably represented by a resource, you would send a HTTP
DELETE
to that resource. The response should be a 4xx error depending on what exactly went wrong .g. in your example, a 410. If it never existed, maybe 404. If you don't have permission to delete it, a 403. In the worst case scenario where nothing fits, you can send a 400. There's no reason, so far as I am aware, not to include a body that gives further details.Admin
Yeah, no worries. In HTTP is just the other way around, hence you have multiple OK states for okayish result, if that makes sense. The errors on the other hand are strictly defined, except for generic ones like 500 when nothing else matches.
There is a design reason with that; for example someone could argue "Why makes it sense to return an error when the end result is the same?". The reason is simply that the end result is a snapshot of an event chain and a snapshot is always incomplete. In other words, if you delete something but for some reason it doesn't exist anymore, well, there could be something very serious going on. It could be a workflow mistake, it could be a security issue due to a man-in-the-middle attack etc. So the information that something could not be deleted because it didn't exist is very much a way more important information than that it the end result is that it is now deleted. Another example would be desynchronization issues; the client could wronglyfully assume that the current user deleted the item and this could result in followup errors like incorrect tracing/logging, continuing with a wrong business cases etc.
I hope this clears up my position a bit as well; I got burned too much in the past by ON ERROR RESUME NEXT APIs or coworkers ignoring what they called soft errors and then you have to waste weeks to find the actual bug :-)
Admin
There are many considerations. Over in mainframe land, we have invented (many decades ago) return codes (status codes) and reason codes: the first describes the severity of the error (or 0 for success), the second describes the reason. Of course getting this somewhat standardized is nearly impossible, so things are often application-specific and not really comparable to other applications or systems. The severity can range from "did what you requested, but incomplete" or "not now, try again later" up to "cannot fulfill your request" or even "subprocess crashed". The reason can the be provided accordingly, like "database said the thing to delete couldn't be found" or "database doesn't talk at all". A good manual often accompanied the list of return codes and reason codes and listed the actions that should be taken by the user. Of course this is all old and stupid and doesn't even exist at all and you cannot learn anything from it...
Admin
REST = Redundant Error Signaling, Ta-da!
Admin
The real WTF is misusing transport result code as service result code. That's a pet peeve of mine.
HTTP codes are meant for the transport. Nothing else. 200 means you reached something at the other side, and technically it returned a reply. If that particular request was looking something up and didn't find it, it should return 200 and a proper result code inside. Why return 404? 404 means whatever URL you wanted to reach does not exist. How would you differ between wrong URL called vs. some item in the DB not found?
Web devs are the bane of sanity.
Admin
LOL. I once did code up a 418. For some kind of testing purpose I think, but I can't recall...
Admin
spooky .... yesterday on my YouTube feed ... https://youtu.be/0gH-hSyWp9o?si=lSRUCocLO1AOHpyj. Includes a great summary of strict REST vs REST-ish. Plus, It is Dylan Beattie, the writer and performer of awesome parody rock songs about coding ....
Admin
Well, as soon as you use an URI in your responses (which is pretty much a given when creating new resources), you use hypermedia. S I'm not 100% sure what he is getting it, does he think hypermedia are only meme pictures and youtube videos? :-)
Admin
No, HTTP codes are for the resources. A transport will always be found (otherwise you wouldn't even reach the server side), but it can be that the resource can't be found, or you're sending a wrong resource which leads to Bad Request (that's what the WTF is about).
Since you're usually getting resources via GET request and have the identifying attributes either as path segments or query parameters in the URL, it's technically correct what you're saying then: The URL points to a non-existing resource. (A URL immediately exists as soon as you use it in the client call, to be a bit pedantic, but it can't be resolved to an existing resource probably.)
Admin
HTTP (with MIME) is a session/presentation layer, not a transport layer. The transport is TCP+TLS.
If a URL is "wrong" in the sense of not conforming to URL syntax, or maybe not following the server's path schema, that's a Bad Request. If it's "wrong" because the data was determined not to be present, that's Not Found.
If your service doesn't narrowly model collections of stored resources, then you're not in the REST game anyway.