3

I want to provide rest api for my iot service to read state of a sprinkler on/off. So far I've come up with two solutions:

  1. GET /api/sprinkler that returns 204 if on and 404 if off
  2. GET /api/sprinkler that returns 200 and {"status": "on"}

The first example is based on this. By returning code 404 we imply that the resource called sprinkler does not exist. Is it even correct assumption?

I can't decide which one is better. I prefer HTTP codes but in this case it gets confusing. Which one should I use?

2

For your case, I believe returning

{ "status" : "off" }

With a 200 status code is "correct".

In practice, it doesn't matter much.

When Fielding published his famous rant on hypertext, he called out a particular error in this way:

Failure here implies that out-of-band information is driving interaction instead of hypertext.

Out-of-band in this case means that the information cannot be deduced from the content of the response and the definition of the type of that content.

In your example, you seem to be trying to communicate the state of the sprinkler in an out-of-band way; "when you get a 404, that means the sprinkler is off" is -- from the perspective of REST -- a cheat.

The in band way to send that information is by sending a representation of the state of the sprinkler. Now, there isn't actually anything that forbids you from sending that representation alongside a 404 -- RFC-7231 encourages servers to include an explanation of the error condition, so that's all right, but the semantics are wrong: "I couldn't find the current representation of the resource, and also here is the representation that I couldn't find."

The Gist API counter-example is slightly different from what you have proposed; you should make sure that you are aware of them.

First, notice that the Gist URI identifies the star, not the gist. In other words, it treats this star as an entity with its own lifecycle, rather than as a simple property. GET /gists/:id/star returns the current representation of the star; when the star doesn't exist, there isn't a current representation to find, and 404 NOT FOUND is appropriate.

In your example, the sprinkler exists always, and it has a property with values on/off. Claiming that the sprinkler wasn't found because the property has the wrong value doesn't really match the semantics.

What would match the semantics would be to identify as a resource the flow of the water through the sprinkler. A 404 response to GET /api/sprinkler/flow makes perfect sense, semantically, when the sprinkler is off and the flow doesn't exist.

Note that this is purely a question of URI/API design -- how well does the spelling of the uri communicate what is going on to the human readers. The computer doesn't care -- it's just following a link. REST doesn't care, so long as the URI is provided by the server, rather than assumed by the client. Putting it another way, the spelling of the URI is analogous to the spelling of a variable name. So if you wanted to claim that /api/sprinkler is the identifier for the flowing water entity, the 200/404 semantics would be fine; you might lose points in the code review for not conforming to naming standards.

However, there is the second point, which is that the Gist API is sitting in front of the book of record for gists and stars. When the description of the star is removed from the gist database, the star really is gone. On the other hand, "sprinkler" sounds like a thing on the lawn out in the real world, that is broadcasting some sort of a signal that you are reflecting through your api. In that case, 404 to indicate off doesn't seem at all suitable -- the signal exists, and you are receiving it, but it is just telling you that no water is flowing at the moment.

Jim Webber's talk on DDD and REST raises what I think is an important point

The web is not your domain, it's a document management system. All the HTTP verbs apply to the document management domain.

I'd take this further and suggest that the status codes also belong to the document management domain. In other words, 404 should mean "I can't find the document you asked for", not "I found the document you want, and I'm telling you I can't so that you know what's in it."

All that said, 200/404 will work, because the constraints against out of band information don't apply to your situation (your api doesn't need to scale out to the size of the web, it doesn't need to be viable as long as the web, you aren't trying to define a bunch of standardized media types to capture all of the information in band, etc).

3
GET /api/sprinkler that returns 200 and {"status": "on"/"off"/"damaged"/"no water".....}

In my view assigning meaning to error codes which already have a defined meaning is a bad idea. How would you distinguish between "off" sprinklers and "client pointing at the wrong url" exceptions?

2

From my understanding, the solution 1 misunderstood the semantics of the HTTP status code.

From RFC HTTP/1.1: Status code Definitions

10.4 Client Error 4xx

The 4xx class of status code is intended for cases in which the client seems to have erred.

In you example, it's a matter of resource representation. Because you are probably thinking that a sprinkler in OFF state is an error, and a sprinkler in ON state is valid.

However, the meaning of a HTTP request and a resource representation are completely different things.

In your case your client asks: "what is the sprinkler state "? The server should check the request (header and body). If it's valid, use code 2xx. If a client made a mistake, use code 4xx. If server has encountered a problem, use code 5xx.

So in your example, the client request is perfectively valid and should be acknowledged with a HTTP status code indicating that it is. So go ahead with 200 code :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.