Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

How do you feel about using StatusCodes to return api information.

/tacos/8 ... not found 404

vs { "meta":{ "errors":["not found"] } }

or something like that without getting into the form of the JSON returned.



The actual HTTP status should be relevant. I don't want to get HTTP/200 with {error: not found}. Instead, useful errors should be like:

HTTP/400 {error: invalid foobar in request. Foobar should be a string, but instead got '123'}

Or something like that. Tell developers what the problem actually was, and potentially how to fix it. http://jsonapi.org/format/#error-objects has some good ideas and suggests a standard.

That said, even discarding the body, you should be able to determine if a request was successful by the HTTP status code alone, IMO. If you made a new thing, 201, thing ain't there, 404, your request sucks, 400, etc. Don't make people using your API parse your [especially true if you've invented your own format] JSON errors if they don't want to.


"Success With Info" is something that just causes problems.

The number of examples we found of "Success with Info" going horribly wrong was abundant. Turns out checking return codes is something people have failed to do pretty much since the invention of the return code...


Is that a failure of the people or failure of the spec?


Failure of people and tools.

Like the sibling comment says, often tools designed to consume HTTP will throw a more severe class of error upon 4xx/5xx, which then changes the codepath significantly, making it more difficult for the programmer to treat 2xx and 4xx/5xx responses similarly for parsing out the headers and the response body.

Web browsers are also guilty of some of these behaviors. They would inject a 'user friendly error page' upon 4xx/5xx. Since they are graphical applications, they have also been used as rudimentary debug/sanity-check tools at the expense of curl.

Together, these forces combined to drive some APIs to respond with a 200 for any response. Often, faithfulness to spec or faithfulness to the intent of the design takes a backseat to making a solution work. The combination of these traditions survives in the myriad APIs that essentially use HTTP as an browser-accessible RPC mechanism.


Which is irritating as all hell at times... the .Net http client does this, which makes snagging the actual response text and code difficult... Same wrt .Net for response codes, there's a lot of errors that can happen with the JSON deserializer for services, but it returns a 500 series error not a 400 series. I usually wrap the on error in the app file, and replace those responses for .Net projects.

Worth noting, not sure if this is improved/fixed in .Net Core based services.

As I mentioned in another thread, I'm in favor of the response always being an object at the top level, with a data property for any response data, and an error property for any errors, errors having a "message" property that is the error message string, and a "code" property that matches the numeric http response code.

This also helps if your error classes have these codes in them, that way the http response code can be set based on the error, defaulting to 500.


Together, these forces combined to drive some APIs to respond with a 200 for any response.

I once had to work on such an API, which was designed that way because of similar limitations in the (third-party?) iOS networking library used by the app that connected to the API (as it was in 2013, anyway).

One can see how thinking of an HTTP request as an RPC rather than a REST request/response would justify throwing an error instead of returning an object, but since REST is now more common than RPC, one would at least expect an option not to throw.


I think in many ways it's just tradition. Old browsers did wonky stuff with non 200 codes and that just created inertia that made people never quite take the effort to follow the spec.


I tend to prefer a simple JSON object that wraps any response...

    { data: any, error: object }
So that only the presence of an error needs to be checked... within the error should always be a friendly message property and optionally a numeric code, that mirrors the response code (404), etc.

    { error: { code:404, message: 'Not found' } }

This tends to work well with error traps in server-side workflows... As to the data/result etc, it can be whatever is needed as a response to the client. For paged results, data/nextToken or something similar are perfectly serviceable imho.

To me an error should be top-level in the response object, as well as meta, and the data itself should be a consistent property and nested as such. Other platforms add their own wrappers which include the headers with the response object. ymmv.


in C# terms...

    //use CamelCasePropertyNamesContractResolver

    public class ApiResponse<T> {
      public T Data { get; set; }
      public Exception Error { get; set; }

      public ApiResponse(T data) {
        this.Data = data;
      }
   
      public ApiResponse(Exception error) {
        this.Error = error;
      }
    }
In this way, all API requests return ApiResponse<TypeOfData>


I agree with tracker1 about a top-level object with data+error keys. Always useful to have an "open" / "extensible" object at the top, so you can add extra stuff as needed. Pagination is a classic example, but another one is debug data, such as profiler timings.

I'm not opposed to having meaningful status codes, but I am opposed to 1) overdoing it and 2) omitting success/failure from the body. The only useful status code distinctions are the ones that browsers respect: success vs failure, redirects, etc. Differentiating 200 OK vs 201 Created, for example, causes nothing but headaches. What would I do differently given that distinct information? What if I do a POST to create an get a 200 when I normally expect a 201? Is that suddenly now a failure?

For API use cases, I only use 200 (success), 400 ("you screwed up"), and 500 ("we screwed up"). For HTML responses, I also use whatever 3xx the SEO people suggest these days.


That's exactly the way to do it. Returning the HTTP status code in the body of the message is just wrong.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: