HTTP status codes are pretty useful. They can tell you when things have gone wrong, and tell you roughly what went wrong. There are, however, cases which don’t seem to be covered by them.
In my job, I work with web services – both writing them and consuming them. Our team, in particular, has a number of projects that provide a web API endpoint to the UI team, and we in-turn, rely on other web services. Some of these web services are written by us, and some are not.
When the user makes a request from the UI, it hits an endpoint somewhere in the bulk of our application. From there, it may go on to call one of these other external services. In general, if the user makes a bad request, we immediately return with an HTTP 400 (bad request), and we try to indicate that the user did something wrong. If something terrible happens (like an unhandled exception), we kick back with an HTTP 500 (internal server error). But what do we do if one of the external services that we rely on fails?
It isn’t necessarily the user’s fault, as the user didn’t do anything wrong. It also isn’t necessarily an internal server error, as it wasn’t our service that failed. Not only that, but all the contents of internal server errors are replaced with a generic message, so as to not leak things like stack traces, which would make reverse-engineering things much easier. So if we return an HTTP 400, it makes it look like the user did something wrong (which isn’t the case). If we return an HTTP 500, we can’t tell exactly what went wrong. In cases like this, we’ve been doing one of two things:
– Return an HTTP 400 error anyway, so we can at least tell what is going on. This is less than ideal, but at least allows us to see what went wrong, and the UI properly displays something to the user.
– Return an HTTP 500, but with a specific content. Rather than having the body of the request replaced with something generic, we fill it out with detail on what went wrong, and hope that the UI knows how to display this properly.
Both still seem a bit less than ideal, but there doesn’t seem to be an HTTP status code for “Hey, something went wrong with an external service, even though you did everything correctly.”