2

I have a RESTful web service which exposes a resource that enables you (the logged in user) to like or unlike a blog post. My question is: what is the RESTfully correct way to express this resource?

My first stab looks like:

PUT /likes/<blog_entry_id> # marks this blog entry as liked DELETE /likes/<blog_entry_id> # marks this blog entry as not liked 

This semantic is at least consistent with the idempotency requirements of PUT and DELETE (i.e. repeated calls to PUT have no effect unless interspersed with DELETEs, and vice versa).

Is there a more conventional design for the management of a boolean HTTP resource?

4 Answers 4

1

You need to include some kind of user identification within your URI. By using the "logged in user" you are violating the resource identification constraint and the self-description constraint.

The only other issue is you seem to be using PUT without passing a body. I've never seen that done before. It's quite possible the HTTP spec allows for it, it is just a bit strange.

Sign up to request clarification or add additional context in comments.

4 Comments

I think it's ok to use the "logged in user". The resource is the blog entry. Who makes "like" is not part of the resource. It can be a parameter on the request, or somehow passed in the body (so it will be content inside the body :), or taken from cookie/header ("logged in user").
@Tarlog No it is not ok. GET /like/13123 would return one result when you are logged in and would return a different result is I were logged in. This is a really bad idea as it makes it very difficult for intermediaries to cache responses. It also makes it difficult for you to see if I like the blog.
It happens everytime. Even at this site, even at this question: the response I get, when I GET the URL for this question is different depending if I'm logged in or not.
@Tarlog Conceptually it is the same resource though, so in this case it is excusable. For it to work though, they had to include Vary:* in the response. This seriously dilutes the benefits of intermediary caching.
0

I think your approach is fine and restful. You can also use POST instead of PUT.

3 Comments

He could, but his request is idempotent. Using an non-idempotent HTTP method, when you are making an idempotent request, is making your request less "visible".
I think PUT is also non-idempotent (didn't check this in spec though, but if it's idempotent, it's will be impossible to use it for updates. Right?) So I don't see a difference from this perspective to use PUT or POST. Since he'll kinda "create like", it looks like POST to me.
PUT is idempotent. w3.org/Protocols/rfc2616/rfc2616-sec9.html It sounds like you are confusing "safe" and "idempotent". PUT is not "safe". You can use PUT to create things also.
0

I would step away from using verbs in resource URLs and use the following schemes:

POST /blog/<id>/fan Send the user-id and other data for the resource you want to create as part of the 'Like' action. I'm supposing JSON here, so this could be an example { "user": "http://..../user/34343", "timestamp": 234353443 }

you could then use GET /blog/<id>/fan to get a list of all users that like the blog post. I would probably send a JSON presentation of the resource that makes it easy to list those users and follow a link the the data of the like action (if there is any)

GET /blog/<id>/fan/<user-id> to get the data of the like action (if there is any)

Comments

0

In a relational database I would call this a good candidate for a join table.

 LIKES ----- id blog_id user_id some_other_attribute_about_this_relationship another_attribute timestamp 

So what you're creating is a Like, or a Fan, or BlogLike, or BlogFan, or a BlogLiker, or, you know, fan_of_a_blog, if you're not into the whole brevity thing.

So these are your verbs:

 GET /likes return a list of Likes POST /likes create a new Like (payload is blog_id and user_id) GET /likes/id return a specific Like resource PUT /likes/id update a Like with new data DELETE /likes/id delete a Like 

This will allow you to ask questions on either side of the join. E.g., Does this user like a certain blog? Is this blog liked by more than 3 users? Et cetera.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.