REST url for nested resources - rest

Which is a proper way of creating REST path ?
Say i have REST resource like,
base_url/api/projects/{projId}/sprints/{sprintId}/.....etc
I have more than 5 path params like this in a resource url. Is it proper to have so many path params or we have to cut it to different resources like,
base_url/api/projects/{projId}
base_url/api/sprints/{sprintId}
...etc
The condition here is , a sprint cannot exist without a project and so on. If we need to cut the resources to different paths, are there any standards on which conditions we can cut them?

REST doesn't care about the URI design. That's a misconception.
The readability of a URI is desirable but not mandatory in the REST architectural style.
As defined in the RFC 3986, the URI syntax is organized hierarchically, with components listed in order of decreasing significance from left to right separated by /. If a sprint cannot exist without a project, you can use the following to express such hierarchy:
/api/projects/{project-id}/sprints/{sprint-id}
However, if the URI gets too long and you have many parameters to pass around, there's not issues in splitting it:
/api/projects/{project-id}
/api/sprints/{sprint-id}

Related

What is the best practice to design the rest api url if one resource identifier is a path

It is straightforward to put resource id into url if it is a int or long type. e.g.
GET files/123
But my problem is that my resource identifier is a path. e.g. /folder_1/folder_2/a.sh because the underlying implementation is a filesystem. So I can not put it as part of rest api url because it is conflict with url path.
Here's approaches what I can think of:
Put the path id as the request param. e.g.
GET files?path=/folder_1/folder_2/a.sh
Encode/decode the path to make it qualifier as part of url.
Introduce another int/long id for this resource in backend. And map it to the path. The int/long type resource id is stored in database. And I need to maintain the mapping for each CURD operation.
I am not sure whether approach 1 is restful, approach 2 needs extra encoding/decoding, and approach 3 needs extra work to maintain the mapping.
I wonder what is the best practice to design the rest api url for this kind of case.
Simple:
#GET
#Path("/files/{path:.+}")
#Produces({MediaType.TEXT_PLAIN})
public String files(
#PathParam("path") String path
) {
return path;
}
When you query files/test1/tes2 via url output is:
test1/tes2
Just put the path after a prefix, for example:
GET /files/folder_1/folder_2/a.sh
There isn't a conflict, since when the request path starts with your known prefix (/files/, in the above example), you know that the rest should be parsed as the path to the file, including any slashes.
Well, my experience designing "restful" APIs shows that you have to take into consideration future extensions of your API.
So, the guidelines work best when followed closely when it makes sense.
In your specific example, the path of the file is more of an attribute of the file, that can also serve as its unique ID.
From your API client's perspective, /files/123 would make perfect sense, but /files/dir1/file2.txt is debatable.
A query parameter here would probably help more, much like what you would do if you wanted to retrieve a filtered list of files, rather than the whole collection.
On the other hand, using a query parameter would also help for future extensions, since supporting /files/{path} would also mean conflicts when attempting to add sub-resources to your files endpoint.
For example, let's assume that you might need in the future another endpoint /files/attributes. But, having such an endpoint, would exclude any possibility for your clients to match a file named attributes.

REST conventions for URI

At work, I've seen routes like this:
/people/:id/edit
But I reckon such routes are hard to build programmatically. To my mind, better, is:
/people/edit/:id
That way, you can do stuff like:
const peopleEditRoute = '/people/edit'
...
<Route path=`${peopleEditRoute}/:id`
...
<Link to=`${peopleEditRoute)/${id}`
However, a colleague commented that '/peoples/:id/edit' is more conventional - it follows REST
Are they right?
As per #jonrsharpe's comment, the route should be:
/people/:id
...for all of GET, POST, PATCH etc...
/peoples/:id/edit' is more conventional - it follows REST
Are they right?
No; REST doesn't care what spelling conventions you use for your resource identifiers.
I reckon such routes are hard to build programmatically.
They shouldn't be. URI Templates are a common solution, and I would expect library support in most languages where you are likely to be writing web code. (Hint: do you really want to be writing your own logic for deciding when to encode your data?)
One consideration for path segments is relative resolution: in particular the use of dot segments to move around an identifier hierarchy.
In other words, if you are in the context of the edit resource for some person, are you more likely to want a relative reference to another resource for the same person, or to the edit resource of a different person?
As noted by #jonrsharpe, if you are creating an API that is "of the web", then you typically will request the modification of a resource by sending a request (PATCH/POST/PUT) that identifies that resource as the request target.
The point here is cache invalidation. Caching is a constraint in the REST architectural style, and general purpose HTTP components know that responses can be re-used to service other requests, and know that successful unsafe requests invalidate previously cached responses.

What is the best way for my rest api uri name to include module name that the ressource belongs to?

I'm wondering what is the best way for my rest api uri name to include the module name that the ressource belongs to? lets clarify this, my rest api should expose the details of Object-A and should also expose the details of Object-B, in this case i can't use the ressource name ipAdresse:port/details because there is two details types.
add to this that i should not use the nesting style like this ipAdresse:port/objectA/:id/details.
So in this case, is it better to do it the following way (include the parent ressource or module name in the url):
ipAdresse:port/objecta/details
or this way (using hyphen):
ipAdresse:port/objectb-details
thanks
There's a small advantage to using path segments, if you have a family of these documents that want to link to each other
/objecta/details
/objecta/comments
/objecta/pricing
These resources can all reference each other using dot segments (ex: ../comments), which means that you don't have to specify the "objecta" part in the links. In other words, you could move the whole family of identifiers to a different location in your hierarchy, and relative resolution would just work.
/objectb-details
/objectb-comments
/objectb-pricing
Each of these paths is a single segment, so dot segments remove the entire path, which you would have to replace (ex: ../objectb-comment), and if you decide to replace the objectb prefix with something else, you also need to update all of the links.
In effect, using / gives you a little bit of future proofing.
That said, if the hyphen-minus is part of the name of the thing, then leave it in the identifier.
/objective-c/comments
If you bring one of these to me in a code review, I'm going to think you've lost the plot:
/objective/c/comments
/objective-c-comments
But of course they will work just as well (the machines don't care) as long as the identifiers match the syntax described by RFC 3986.

How to create right API URLs for getting data

I'm creating a simple API which works with geographical data.
Some URLs look very simple like:
GET /towns/{id}
or
GET /towns
Now I want to get a town by alias, should I use this kind of URL?
GET /towns/alias/{alias}
What if I also want to get a list of towns located near certain town?
GET /towns/closest/{id}/radius/{radius}
I understand that my URLs can be any I want. What is a canonical way to do it?
I understand that my URLs can be any I want. What is a canonical way to do it?
There isn't really a "canonical way" to design URLs, any more than there is a canonical way to name variables -- there are only local spelling conventions.
RFC 3986 distinguishes between hierarchical and non-hierarchical data:
The path component contains data, usually organized in hierarchical form, that, along with data in the non-hierarchical query component (Section 3.4), serves to identify a resource within the scope of the URI's scheme and naming authority (if any)
The effect of using hierarchical data is that you can take advantage of dot-segments to compute one URI from another.
For example
/town/alias/{alias}
/alias/{alias}
Both of these spellings are "fine", but /town/alias gives us the option of using dot segments to specify an identifier under /town
/town/alias/abc + ../123
=> /town/alias/../123
=> /town/123
That can be handy when it allows you to re-use a representation for multiple resources in your hierarchy.
Yes it can possible through the URL routing.You can send any number of parameter through url.
Can you please confirm the technology you used?

How to construct URIs for RESTful service that operates tree-like data?

Assume I have tree-like data, e.g. “files” and “folders”, basic operations are “list folder”, “create folder”, “rename”, “create file”, “fetch file”.
So how can I construct URIs for RESTful service? I've tried a few times but all solutions look not very nice to me.
For example, if I have “folder” resource referenced by URI `http://example.com/rest/here_path_to_folder, how can I list folder items? Fetch “file” from this folder?
I've seen Amazon AWS docs, they are using not very clean approach—passing “folder” path and folders delimiter as query arguments, this could cause ambiguity because different URIs will reference the same resource. Also I've tried appending keywords to the end of path, so listing “files” looked like:
GET /rest/path/to/folder:list HTTP/1.1
Rename:
POST /rest/path/to/folder:rename?target=NEW_NAME HTTP/1.1
But it still look terrible for me. So do you know any success stories of using 100% REST on hierarchial data?
I think it should be quite simple to use URIs to represent your hierarchical data structure. Although URIs don't strictly imply hierarchy (some people like to keep then completely opaque), meaningful URIs do have a naturally hierarchical feel and they should map nicely to your file/folder example.
In a RESTful system, resources have a common interface which (in your case) is defined by the HTTP verbs. The URI identifies a resource, REST dictates that it shouldn't be used to indicate the operation you are trying to perform.
So instead of
GET /rest/path/to/folder:list HTTP/1.1
I'd propose that to list the contents of a folder (find out it's state) you simply use:
GET /rest/path/to/folder HTTP/1.1
This should return a list of URIs which represent the files and subfolders that this folder contains. Then to get the contents of one of the files, I might then invoke:
GET /rest/path/to/folder/myfile HTTP/1.1
Renaming is a bit more tricky. In some cases a DELETE followed by a PUT would work, but I'm guessing you want to retain the folder contents without having to re-upload. One option is a PUT where the body contains a new folder path, which responds with a 204 and the Location header value pointing to the newly created folder (as described in 'Renaming a tag' here). Optional: If you want to be really friendly to your users, you could also return a 301 status (Moved permanently) with a link to the new URI if the anyone makes a request to the old URI.
Remember the path is just one of the properties that makes up the state of a folder, you can update that state with PUT without needing to introduce a custom 'rename' operation. In your case, you happen to use the path to decide your URI, but it's perfectly valid for a state change to cause a change in the URI.