0

I am starting to learn REST (for my own project), and at the same time experimenting with Philips Hue API. I have discovered a strange IMO effect: to switch a light on, I need to PUT {"on": true} to /api/<KEY>/lights/6/state. The light status can be retrieved with GET on /api/<KEY>/lights/6/, and I receive e.g.

{
    "state": {
        "on": true,
        "bri": 113,
        "alert": "none",
        "reachable": true
    },
    "type": "Dimmable light",
    "name": "Light 6",
    "modelid": "LWB006",
    "manufacturername": "Philips",
    "uniqueid": "00:17:89:01:11:57:da:8d-0b",
    "swversion": "5.38.1.15095"
}

However I cannot GET anything from /api/<KEY>/lights/6/state:

[
    {
        "error": {
            "type": 3,
            "address": "/lights/6/state",
            "description": "resource, /lights/6/state, not available"
        }
    }
]

I am not sure I actually read it anywhere, but the feeling I've got from reading many different texts about REST tells me that if I can PUT /api/endpoint, I should also be able to GET it back. So if I designed the API, it would be either PUT {"state": {"on": true}} at /lights/6 or GET /lights/6/state would have returned {"on": true}.

Is there any general agreement on this?

UPDATE: As was righteously mentioned, I haven't actually referenced anything. Trying to find references now, I managed to find a popular tutorial, which seems to start plain wrong to me:

PUT - Used to create a new resource.
POST - Used to update a existing resource or create a new resource.

I believe all other resources, e.g. this and this, are clear in that POST should not be used to update.

But in general, REST is based on URLs that identify "resources". So if I can PUT data to a resource, I should also be able to GET data from that resource. I couldn't find it written explicitly anywhere, but doesn't the notion of resources imply it?

texnic
  • 3,959
  • 4
  • 42
  • 75
  • yes you are wrong . I recommend going through basics of REST . GET will only give you result if its been declared in service side as GET and same with other methods - PUT ,POST , DELETE .. there is no agreement such that with the same URI able to do GET and PUT .. – Rohit Sep 15 '16 at 00:37
  • 1
    @Rohit, you're really fast :) Could you convert your comment to an answer? – texnic Sep 15 '16 at 00:39

2 Answers2

1

I guess I'm kind of irked by the Phillips Hue way. My understanding has always been that you're working with resources at locations. POST should create a new resource of the specified type, PUT should update the resource it points to (or create one at the given location if it doesn't exist) etc.

I feel like this might be more conventional if it were POST .../lights/:id/states and it created a new state resource for the given light, describing its current state perhaps. That'd also have the (conventionally) advantage of meaning there was a history of states for the device. (eg. GET .../lights/6/states/3 would exist, too)

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

If state is just an attribute of the light and not treated like a resource of its own I'd expect the behaviour to be as you described: PUT .../lights/6 with state information in the body.

dave
  • 1,127
  • 2
  • 10
  • 26
  • Hi Dave, I don't know if I agree with your vision (is state a new resource or a an attribute of an existing one?), but the last sentence is clear :) My question however was about not being able to get something that I can put. – texnic Sep 15 '16 at 15:33
0

We had a discussion about this at my work. In my experience, in the early days of Get/Post/Delete/etc., only GET and POST were used; POST being used to send data either in large volume or "hidden" from the URL. The other HTTP methods were implemented basically as a sub-protocol using GET/POST as the "carrier". This is possible because the REST service can do whatever it wants once it receives the request. As network services became more disciplined, the various HTTP methods started to be used appropriately.

Your experience with the Philips API makes sense - to change something, you use the PUT method, to get status, you use GET. I have no explanation why GET fails when trying to get the state.

The texts you reference (without a reference) seem to imply that if you set (PUT) a value of something you ought to be able to read (GET) that something's value. And it would make a lot of sense to use a similar URL. But it boils down to how it was implemented; there is little more than down-voting to stop you from writing a GET interface that DELETEs from a database (don't do that).

When you write your REST API, I highly recommend that you follow the current Best Practices, use the HTTP methods as defined and as fit your application. It will make the API intuitive and your backend code will be modular and easy to maintain.

user3481644
  • 398
  • 2
  • 12