REST: nested resource url when you don't want the parent ID visible - rest

I read that the route for getting a nested resource in REST should look like this
/articles/:articleId/comments
The owner (:articleId) of the child resource will be visible.
But what if you have an owner that you don't want the client to know about?
For example, let's say I have an app where users have anonymous posts. I wouldn't want other users to see the client fetching the post by /users/123/post/321 because users could identify who wrote the post from the id and it wouldn't be anonymous.
Is the id necessary? Is it ok to instead do /users/posts/321 if all posts have a unique id?

There are no actual requirements for the URL format. It can be whatever you'd like it to be.
If it were me, I would use simply /posts/321 and leave users out of it, since a particular user isn't specified in your URL at all. I think that's the clearest way to handle it in your case.

Related

Should I POST to the collection when creating a resource with a known ID in my REST API?

I'm implementing a new REST API. In this API I typically POST to collections to create resources. For one of my resources, the ID is known before it is created. Does it make more sense to post to the collection with the ID in the body or to post to the instance (as yet non-existent) with the ID in the URL?
I'd say keep the existing endpoint and just add the ID in the body when POSTing to that collection, there's no point in adding a new separate route for what's basically the same thing.
From another thread: https://stackoverflow.com/a/18474955/1851581
You can also use PUT with the ID in the URL, instead of POST.
PUT is used for upserting, covering mainly updates but also the creation of the resource if it doesn't exist.
I ended up posting to the collection with the ID in the body. That keeps with the pattern elsewhere in my API. The only difference here is that the ID is supplied in the body.

Restful Collections - how to either remove OR delete items

I read quite some stuff about RESTful API Design.
But when it comes to the implementation, it wasn't that easy anymore.
I got stuck at the following problem:
Assume the following 2 endpoint:
/api/v1/users/:id
/api/v1/users/1/friends/:id
As we all can see, friends is a collection of the resource user.
A user can have n-friends in his friendslist (by standard this would be many to many, but for now, let's assume this to be one to many).
Okay, now i want to REMOVE a user (id=3) from the friendslist of user 1 by doing the following HTTP-Request:
DELETE api/v1/users/1/friends/3
And this is where i got stuck - either the request deletes the whole user resource which has id = 3 or removes the resource from the collection. Because both would be valid Restful implementations i think.
So the question is:
How to remove an item from the collection without deleting the original resource
I hope that this question is no duplicate - but i did google a lot to find the answer. Maybe i don't know the related technical term to find some pleasing results...
Thanks in forward.
The approach to REST looks fine but that really only speaks to path format and HTTP verb. The problem must be in your application code or app routes.
I think it is better that DELETE api/v1/users/1/friends/3 would be used to delete user 3, just like DELETE api/v1/users/1 would be used to delete user 1.
To remove just user 3 from being a friend of user 1 I would use DELETE api/v1/users/1/friends and specify a filter to only remove friends with the id of 3.
DELETE api/v1/users/1/friends without a filter would remove all friends of user 1.
Likewise to add friends of user 1 I would use PUT api/v1/users/1/friends and specify the ids of the friends to add.

REST URI Design for resources that belong to a specific user

Assume I want to create a very simple todolist RESTful API, where each user owns a list of todos. The user is already authenticated over http BASIC or DIGEST.
At this point I am not sure what the URL scheme should look like.
Would it be:
http://servername/todos/
where my server filters the appropriate todos according to the authentification given to me by the http header.
Or should I include the username in the URI instead:
http://servername/users/username/todos/
On some websites I have even seen that they hand over the user name as a parameter like this:
http://servername/todos?username=babsi
As far as I can tell all three choices are stateless as I always receive the username, but just over different sources. From what I can tell to make sure that the URI is accessed by the proper user I always need to check the http header anyways. So which of the ways would you consider the best URI design in REST or should I do in a different way entirely?
You can use the following:
http://servername/todos/ GET list all todos
http://servername/users/ GET list all users
http://servername/users/{user_id}/ GET list an user
http://servername/users/{user_id}/todos/ GET list all todos for an user
I think the point here is how you want to design the relationships between your resources, if a todo just can exist in the context of an user use a hierarchy like approach as above.
As general rule i usually follow this:
Use path variables to encode hierarchy: /parent/child
Put punctuation characters in path variables to avoid implying hierarchy where
none exists: /parent/child1;child2
Use query variables to imply inputs into an algorithm, for
example: /search?q=jellyfish&start=20
Having the username in the URL depends on what you want to do (if anything at all) when you receive a request where the username in the URL does not match the authentication. If you want to re-authorize the user in this situation then yes - it's OK to have the username in the URL, otherwise it's OK to have it just in your header or other authentication scheme if there is no such need.
One fairly common example of a valid requirement would be if you have to have a main user (or group of such users) that can impersonate other users.
When the user in question is always the user who is holding the authentication token, then use something like "me" in your path.
http://example.com/users/me/<path-to-inner-resource>
Otherwise, user should be treated just like any other resource in your system, in which case the resource identifier for that user becomes a part of the path.
http://example.com/users/<id>/<path-to-inner-resource>
Take a look at Twitter APIs as an example.
https://developer.twitter.com/en/docs/twitter-api/users/follows/quick-start/follows-lookup

How do I "unlike" a built-in like in a single request?

When you want to "unlike" a built-in like action on an open graph object, you have to send an HTTP DELETE with the id of the like story itself. But that requires either:
Querying the graph for the ID of the story before deleting it, or
Stashing the ID that's returned when you create the like in the first place.
Neither of these are satisfying solutions. It would be nice to be able to do this all in a single request, preferably with nothing more than the URL of the liked object.
Because this modifies the graph, the Graph API has to be used, right? AFAIK, FQL is still read-only.
Half the battle is figuring out a way to use the Graph API to look up the ID of the like story given the URL of the liked object:
GET http://graph.facebook.com/me/og.likes?object=http://url.to/your/object&fields=id
Once you have that, you can name it in a batch query, then refer to it from the DELETE request using JSONPath (details here under "Specifying dependencies between operations in the request"):
POST http://graph.facebook.com/
batch=[
{"method":"GET", "name":"like_id", "relative_url":"me/og.likes?object=http://url.to/your/object&fields=id"},
{"method":"DELETE", "relative_url":"?id={result=like_id:$.data[0].id}"}
]

Convert any facebook URL into a graph ID

Is there a simple, reliable and potentially future-proof way to extract a graph ID from the API given any facebook URL? By "any facebook URL" I mean the URL for a personal profile, page, group, etc. All these things have various formats so I imagine there must be something in the graph API to definitively convert a facebook URL into an ID, right?
No, there isn't a way to do this simply within the API. You will need a set of pattern matching to match the various types of urls to extract either the id (album,note,photo,status) or username.
For example
Photos
facebook.com/photo.php?fbid=10100213582161431&set=p.10100213582161431&type=1&theater
https://graph.facebook.com/10100213582161431
Posts
facebook.com/zuck/posts/10100210345757211
https://graph.facebook.com/10100210345757211
Pages
facebook.com/pages/Joel-Spolsky/106083232757300
graph.facebook.com/106083232757300
Videos
facebook.com/video/video.php?v=10150398154330484
graph.facebook.com/0150398154330484
Events
facebook.com/events/138745136241434/
etc ...
Then it gets further complicated that even if you were able to get a silver bullet function that handles all these links your app would need to grant access to numerous permissions in order to access certain objects.
You may be able to get away with most links that have the id at the end but not all. So you can maybe use a regular expression catching links that end in numeric characters.
There is! You are looking for the object_url table, which you can query using FQL or directly with a request. See here: http://developers.facebook.com/docs/reference/fql/object_url/
EDIT:
You can also do this, but obviously less optimal:
function getObjectByUrl(url, cb) {
FB.api("/" + url.replace(/^.*?www.facebook.com/, ""), cb);
}