that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
that_james's comments
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
I should have been clearer about this relating to HTTP RPC. I updated the post.
That said, after reading the responses here, I can see that what I've actually achieved is making the response harder to determine for the client, which is antithetical to the objective.
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
I was hoping to start a discussion around using HTTP status codes as domain error codes, as opposed to an opinionated payload.
Maybe not as clear as I could have made it.
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
Not really sure why you think I'm of the opinion only 2xx codes can have responses, perhaps I could have been clearer.
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
But then what's the point of an API contract if it's not describing the returned data? What I'm arguing is the opinionated payload provides a lot of the same value. Or am I missing something?
The monitoring systems would naturally not be stoked to see 2xx codes containing errors, but I'd just ping the monitoring system out of my application server anyways. Not sure if that's better or worse though.
I've done like little to no platform engineering and I may be gravely underestimating the consequences of doing this, but it works well with prometheus.
Perhaps I am a fool though :) but how else would I find out if I didn't put my ideas out there :D
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
Oof, that's a hell of a good point. So much for that plan lol
> Anyway - I'm entirely with you on the foolishness of using 404 to mean both "your URL is messed up" and "I couldn't find the resource you wanted". Seems like, for REST, you'd want to return a 400 (malformed request) or something if your URL was borked rather than overloading 404.
Yup, that's the headache I'm trying to muddle my way through.
Really it's less "this is how to build APIs" and more "have you considered your consumer when you return data?". But I think even in that context your point stands better.
Back to the drawing board it seems.
At least I can generate more content now :D
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
I would like to point out a few of the detractors are conflating REST and HTTP RPC, I avoided using the term REST for a reason :)
BUT, that being said, lots of good arguments against this stance. I appreciate the feedback :)
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
But that's a good point about the transport layer.
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
If you ask for an employee that doesn't exist, is it a failure? Or is it just a negative, but expected response?
Perhaps that's a stupid question though.
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
Why not ping the monitoring when you encounter the business error?
From that perspective, a stream of HTTP errors could indicate a more specific kind of infrastructure failure vs just clients sending garbage.
Happy to admit I'm wrong though, it's why I posted it here, see what others think
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
I've said it in other responses, but maybe I should have been specific that I was referring to HTTP RPC (explicitly not citing REST for a reason).
Perhaps a combination of both is best, but in my experience a nice clean break between these 2 layers at the protocol level helps clients simplify their handling of responses.
2xx: Go ahead and parse (another commenter pointed out Content-Type. That one always gets me)
4xx/5xx: Something bad happened and the request wasn't processed by the server, either because it blew up (5xx) or because you did something _very_ wrong (4xx)
The objective is clarity to the caller.
It's a little obtuse but I think it works well with that objective in mind.
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
In the context of RPC, is it still impractical? It feels clearer to me, but I might just be continuing my own confusion now
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
But then it would be both, wouldn't it?
I know I have a JSON payload representing a domain response because of the 2xx response code AND the Content-Type header?
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
This is _specifically_ about HTTP APIs. REST is not a synonym for HTTP but there are much better resources out there that rant on about the important of hypertext and URL support etc.
This is mostly about the perspective of consumers.
>It does not matter too much which part of the URL is the one that is causing the URL to be wrong.
Your consumer disagrees, they'd like to know if their URL was fat fingered or if a record was missing. My argument is 404 is inappropriate because the web service exists, but the record doesn't.
> Thus `api/v11/employees/1` and `/api/v1/employees/100` both are wrong resources.
I can't say this is wrong, but it doesn't feel right. `/api/v11` straight up resolves to nowhere. Maybe this an instance where Gone is better than Not Found?
> Nobody is stoppping anyone to add response body to a 404 to indicate which nested resource is invalid. That can be added as a debug message for the developer for example.
100% agreed. It's just a thought I had while debating with my team.
I posted this here for this exact kind of feedback :D good points raised
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
I've never seen one in the wild, but looking at the docs is that error not reserved for using the wrong protocol (such as 1/1 when the server only accepts 2 or something?)
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
It's also why I raised the issue of where your "server boundary" is. I dunno how else to phrase it, but what I mean is the separation of domain logic and technical logic.
In my understanding, 400 denotes an HTTP request that doesn't comply with the RFC (missing headers, bad format etc) but I also don't disagree with what you're saying, because the user did send a bad request.
Of course, you could always do both :) Send the opinionated payload with a 400 error.
As long as your consumer can reason about what went wrong, then I guess that's in line with the objective I was trying to get across.
that_james | 3 years ago | on: I've been abusing HTTP Status Codes in my APIs for years
The objective mostly was to try help form a way of reasoning about HTTP APIs from the consumer's perspective
> error 400 for all semantically-invalid requests
Counter point: Passing `a` to the example endpoint is not semantically-invalid from the perspective of HTTP, it's a perfectly valid URL. Nothing about that request is invalid, it's only invalid to the business layer, which has nothing to do with the HTTP layer. Put another way: The server _is_ processing the request, that's how it send back the "employee not found" record. I guess it depends where you want to draw the boundary of server.
Which is not to say you are wrong if you return a 400, but I suspect you might get a couple queries about it from consumers.
The objective was mostly about clarity. Maybe I'm being over-simplistic, but I like the idea of using protocol errors for protocol problems and domain errors for domain problems. Just keeps client-side logic cleaner in my experience
After knocking it around in my head, I concede I am wrong :) HTTP is, after all, an Application layer protocol.
Whilst I remain unconvinced by some of the arguments, that one that got through to me was mostly about the reasoning behind using an application layer protocol in the first place: standards. And this breaks the crap out of those standards.
The correct answer is probably closer to a combination of status codes and a _clear_ response message (as well as the correct Content-Type header!)
An empty 404 is ambiguous, which is surprising to nobody :) fair points all round