Let's say we have an API with a route /foo/<id>
that represents an instance of an object like this:
class Foo:
bar: Optional[Bar]
name: str
...
class Bar:
...
(Example in Python just because it's convenient, this is about the HTTP layer rather than the application logic.)
We want to expose full serialized Foo
instances (which may have many other attributes) under /foo/<id>
, but, for the sake of efficiency, we also want to expose /foo/<id>/bar
to give us just the .bar
attribute of the given Foo
.
It feels strange to me to use 404
as the status response when bar
is None
here, since that's the same status code you'd get if you requested some arbitrarily incorrect route like /random/gibberish
, too; if we were to have automatic handling of 404 status in our client-side layer, it would be misinterpreting this with likely explanations such as "we forgot to log in" or "the client-side URL routing was wrong".
However, 200
with a response-body of null
(if we're serializing using JSON) feels odd as well, because the presence or absence of the entity at the given endpoint is usually communicated via a status rather than in-line in the body. Would 204
with an empty response-body be the right thing to say here? Is a 404
the right way to go, and if so, what's the right way for the server to communicate nuances like "but that was a totally expected and correct route" or "actually the foo-ID you specified was incorrect, this isn't missing because the attribute was un-set".
What are the advantages and disadvantages of representing the missing-ness of this attribute in different ways?
I wonder if you could more clearly articulate why a 200
with a null
response body is odd. I think it communicates exactly what you want, as long as you're not trying to differentiate between a given Foo
not having a bar
(e.g. Foo.has_key?(bar)
) and Foo
having a bar
explicitly set to null
.