0

one of the advantages of http REST over SOAP for example is that REST utilizes machine language/convention to convey a lot of the meaning (ie an http POST means create, http DELETE means remove.. etc).. so it removes a lot of ambiguity and room for error that's associated with free for all protocols like soap..

that said, I was wondering if it's desirable to extend that concept into http response types.. specifically when it comes to errors.. so lets say i got this api call, where I want to get the number of available drivers around me:

get api/drivers

if some drivers are found.. then normally u'd return json with the number of drivers + details etc.. but what happens when 0 drivers are found? should you return the data in the same format with 0? or should you utilize http response codes and return an http 404 code?

although using a 404 code would be consistent with the idea of convention over configuration.. and letting machine language do most of the interpretation/explanation.. i found some engineers who complain that a 404 response is more like an exception being thrown, and it's as if something went wrong, when it is perfectly normal to have 0 drivers available in the vicinity of the user.

enter image description here

update:

in the case of finding amount of nearby drivers/restaurants etc.. the answer is probably obvious.. but what happens when you're creating a rest api that makes an assumption.. for example this one

get api/drivers/eta

which means get the eta of the nearest driver.. what happens where there are no drivers around? would it make more sense to use 404 here or return a normal 200 and explain in the json body that no drivers exist?

abbood
  • 23,101
  • 16
  • 132
  • 246

4 Answers4

2

A GET request to a collection resource can return an empty collection. This response is 200 OK since the (empty) collection exists. Returning 404 Not Found would mean that no collection exists which is not the case.

Request:

GET /restaurants

Response:

200 OK
Content-Type: application/json

{
  "count": 0,
  "restaurants": []
}
Julian Reschke
  • 40,156
  • 8
  • 95
  • 98
  • ok.. what about if you want to get the eta to the nearest driver when there are no drivers around? see updated question – abbood Jun 24 '14 at 06:51
2

I covered this in the Endpoint Theory chapter of Build APIs You Won't Hate, but I can give a quick rundown.

... so lets say i got this api call, where I want to get the number of available drivers around me:

get api/drivers

Weeeeell it's not "around you" unless you pass it some coordinates, seeing as it's stateless and we don't want some rando background logic tracking the users location. Maintaining that state would be tough and strange, so let's just pass it on request.

GET /api/drivers?lat=X&lon=Y

if some restaurants are found.. then normally u'd return json with the number of restaurants + details etc.. but what happens when 0 restaurants are found? should you return the data in the same format with 0? or should you utilize http response codes and return an http 404 code?

We jumped from drivers to restaurants here which confused me a little, but to answer the more general question: empty collection is a 404?

Nope! A collection is a resource (woah!) an actual thing that exists. If you have a bag of spanners, then the bag is a resource just as much as the spanners are resources. With me?

So, you have this spanner bag. You lend out all the spanners, but you still have the bag. Or maybe you've just got the bag and no spanners have arrived yet. Or maybe somebody asked if you have a purple spanner.

All of these requests will return an empty bag of spanners.

Basically, GET /restaurants should always 200 OK, until the day you deprecate and remove the concept of restaurants from your API. If no restaurants exist, then that's ok, you have an empty array of restaurants.

what happens when you're creating a rest api that makes an assumption.. for example this one

get api/drivers/eta

which means get the eta of the nearest driver.. what happens where there are no drivers around? would it make more sense to use 404 here or return a normal 200 and explain in the json body that no drivers exist?

That would be a rando-RPC endpoint all up in your REST API, so get that outta there for starters.

If you have a specific order that you are expecting to see drivers progress on, then you do not need this arbitrary RPC style endpoint. What you could do is have this:

GET /apis/orders/<uuid>

That could very easily have an "eta" field in minutes, but I think another endpoint could improve that:

GET /apis/orders/<uuid>/updates

This list would have updates as the kitchen finishes preparation, another as the driver picks up, another as the driver is half way, another when the driver is pulling up, etc.

Again, if there are no updates that's just an empty bag of updates.

Phil Sturgeon
  • 30,637
  • 12
  • 78
  • 117
  • hey @Phil Sturgeon i tried to buy the "ebook" but it's telling me that there are shipping charges.. is that an api error? – abbood Jan 05 '18 at 06:05
  • That's so weird! It looks like you found a way around it and the order has been accepted and fulfilled. I'll bug you on your email to see if we can figure out why the heck that was happening, as it definitely should not. :) – Phil Sturgeon Jan 05 '18 at 12:28
  • i ordered the book.. got confirmation.. but no book! what do i do now? – abbood Jan 05 '18 at 12:30
  • I have records of the email with the link going to you, but I think you might have used an incorrect address. Please email phil@apisyouwonthate.com and I'll send you your download link manually. – Phil Sturgeon Jan 05 '18 at 12:35
  • ok let's talk about this via email.. it's getting messy here on SO – abbood Jan 05 '18 at 12:43
  • good stuff great read! [here](https://stackoverflow.com/questions/48122263/how-to-track-which-seeders-got-applied-in-laravel) is a question inspired by your book :) – abbood Jan 05 '18 at 22:39
  • @PhilSturgeon what do you mean by "rando-RPC" ? would it still be undesirable to if it were [api/drivers/{driverId}/eta] ? what if there is no driver by that ID registered should response code be 404 then (I have the same case in an API) ? – MHosafy Jan 15 '19 at 22:16
  • @MHosafy if you create the concept of an ETA resource then its no longer RPCish, so that'd be fine. If the URL is invalid then yes a 404 is appropriate, so if there is no driver the URL is invalid. – Phil Sturgeon Jan 16 '19 at 17:58
1

When designing a solution take into account the following: Ease of use, simple implementation and maintenance.

Concerning the HTTP error codes: although it has advantages over defining your own codes, using it could interfere with the normal HTTP errors thus limiting your options for future usage of these logs like analysis for quality, intrusion detection...

Then the calling side has to deal and distinguishes between an HTTP error codes and application/api error codes. So if you get a 500 will this be an internal server error for some un-caught error or someone just fired it because they missed some mandatory params. if you get 404 is this is because you miss typed your URI (or URL changed) or because the server did not find some data you are requesting e.g. in the above examples "no taxis found"

Look at some apis implemented like Google apis, FB..they are have return codes defined within the returned reply (whether json/xml/text...)

Shadi Moadad
  • 78
  • 1
  • 7
0

First things first, /api/drivers/eta does not represent a resource on the server. We are trying to model it as a resource which is not a RESTful design; but lets assume your business needs to support such a endpoint. 404 should be used when a resource identified by the URL cannot be found on the server. So in this case, 200 OK with empty response makes more sense. Or if you want this to be treated as an error case, you can use 422 or 400 with appropriate message in the response payload

Request:

GET /api/drivers/eta

Response:

200 OK Content-Type: application/json

{ "count": 0, "drivers": [] }

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
java_geek
  • 17,585
  • 30
  • 91
  • 113