I'm developing a web application that has a backend API, which is going to be primarily used by a reference frontend application, but other clients can use it too.
The data my API sends has a specific type structure. I'm using Rust's type system, which has enums whose options may have additional data inside them. For example, the responses of a route that retrieves an article may be modeled like:
#[derive(serde::Serialize)]
#[serde(tag = "status")]
enum ArticleGetResult {
Exists {
name: String,
content: String,
score: i32,
},
NotFound,
Redirected {
new_id: usize,
},
DatabaseError {
error_text: String,
}
}
It's considered good form to provide useful status codes in APIs, and also headers, and the backend does send those when applicable. However, because of technical reasons, it's somewhat difficult to get access to these in the frontend code, so instead I only use the response body and ignore the status code and headers.
-> GET /articles/1
<- 200 OK
{"status": "Exists", "name": "Article", "content": "article content", "score": 5}
-> GET /articles/2
<- 404 Not Found
{"status": "NotFound"}
-> GET /articles/3
<- 301 Moved Permanently
Location: /articles/4
{"status": "Redirected", "new_id": 4}
-> GET /articles/4
<- 500 Internal Server Error
{"status": "DatabaseError", "error_text": "some error happened"}
Are there any particular downsides to not using the status code and header info in client code, and instead only using the response body's info?
Are there any particular downsides to not using the status code and header info in client code, and instead only using the response body's info?
Yes - largely it comes down to this: you may be limiting the kinds of HTTP intermediates you can introduce into your system. In other words, can your system still work if the client is passing its traffic to a proxy, or the server is receiving its traffic from a reverse proxy?
The problem being that these components will be assuming that other components sending and receiving HTTP messages will understand HTTP, and will expect those components to be able to correctly handle HTTP metadata.
Example: some network error occurs, and the system starts sending general purpose 504 Gateway Timeout responses with some message body that you don't control. How does your client interpret that message?
Part of the point of choosing a general purpose application protocol (HTTP) is so that we can use general purpose components to do a lot of the heavy lifting, rather than building everything for ourselves.
In a situation where you control the client, the server, and the topology in between, those concerns might be less important to you than (for example) the advantages of writing the client in the style that you suggest.
And that's fine.
I'd suggest capturing in a decision record all of the factors that you considered when making this choice, so that they can be reviewed by posterity if local conditions change.