I have a system where logged in users can vote like or dislike on posts. If they try to like a post which has already been liked, they ll remove its vote. Same applies for dislike. As a REST newbie I am trying to come up with a url scheme for this and it is confusing
Currently, my urls look like this
POST /news/vote/social/:feedItemId/:vote(like|dislike|reset)
A single endpoint is doing everything and logged in users are the ones who can actually vote
After reading some other answers on stackoverflow it seems there are other possibilities as well like
PUT /news/vote/social/:feedItemId/(like|dislike)
DELETE /news/vote/social/:feedItemId
I have seen other answers where the userId is also included in the url because it says REST API design should not reflect statefulness
PUT /news/vote/social/feedItemId/:userId/(like|dislike)
DELETE /news/vote/social/:userId/:feedItemId
The problem with these urls is any person can update any userId s vote unless some backend check is involved
My question, is what is the right way to handle these considering only logged in people should be able to update only their vote?
It sounds like you probably should take a look at Custom Methods.
Since this is a per-user action, it makes perfect sense to have custom methods that upvote and downvote, where each one acts as a toggle for +1 or -1. For example:
POST /items/1234:upvoteon a new post would add +1 (points=1)POST /items/1234:upvoteon that same post again would take away the upvote (points=0)POST /items/1234:downvoteon that same post again would add -1 (points=-1)POST /items/1234:downvoteon that same post again would take away the downvote (points=0).One extra consideration is the following sequence:
POST /items/5678:upvotewould bring points to 1.POST /items/5678:downvoteright after would both take away the upvote and apply the downvote, bringing points from +1 to -1.(and vice-versa for the reverse sequence)
You mention that this requires some back-end check, which is absolutely correct. If you implement your API where any user can apply upvotes or downvotes from any other user as long as they know the user ID, you've got a security risk. So the correct way to handle this is to use the back-end to pull the user ID from the session after they've signed in (and not from the URL where anyone can fill in the blank for which user they're voting on behalf of).