I prefer simplicity and using the first example but I’d be happy to hear other options. Here’s a few examples:

HTTP/1.1 403 POST /endpoint
{ "message": "Unauthorized access" }
HTTP/1.1 403 POST /endpoint
Unauthorized access (no json)
HTTP/1.1 403 POST /endpoint
{ "error": "Unauthorized access" }
HTTP/1.1 403 POST /endpoint
{
  "code": "UNAUTHORIZED",
  "message": "Unauthorized access",
}
HTTP/1.1 200 (🤡) POST /endpoint
{
  "error": true,
  "message": "Unauthorized access",
}
HTTP/1.1 403 POST /endpoint
{
  "status": 403,
  "code": "UNAUTHORIZED",
  "message": "Unauthorized access",
}

Or your own example.

  • ramble81@lemm.ee
    link
    fedilink
    arrow-up
    0
    ·
    3 months ago

    Giving back a 200 for an error always makes me bristle. Return correct codes people. “But the request to the web server was successful!”

    • lemmyvore@feddit.nl
      link
      fedilink
      English
      arrow-up
      1
      ·
      3 months ago

      You should consider if you really want to integrate your application super tightly with the HTTP protocol.

      Will it always be used exclusively over a REST-ful HTTP API that you control, and it has exactly one hop to the client, or passes through hops that can be trusted to never alter the HTTP metadata significantly? In that case you can afford to make HTTP codes semantically relevant for your app.

      But maybe you need to pass data through multiple different types of layers and different mechanisms (socket protocols, pub-sub, file storage etc.) In that case you want all your semantics to be independent from any form of transport.

    • gencha@lemm.ee
      link
      fedilink
      arrow-up
      1
      ·
      3 months ago

      I don’t necessarily disagree, but I have spent considerable time on this subject and can see merit in decoupling your own error signaling from the HTTP layer.

      No matter how you design your API, if you’re passing through additional layers, like load balancers and CDNs, you no longer have full control over all responses your clients receive. At this point it may be viable to always signal a successful backend connection with a 200, even if the process resulted in a failure.

      Going further, your API may include partial success scenarios, think batch processing, then the result could be a mix of success and failure that doesn’t translate to HTTP status.

      You could even argue that there is really no reason to couple your API so tightly with a concept of the transport layer it uses.