Which will be better rest API url according to rest standard?

Viewed 108

I have package as resource. A package can have parent package and so on. On top of hierarchy is the root package. Now the use case is:

Given a packageId of any package (not necessarily root package), I want to retrieve details of the root package that exists in its hierarchy at top.

I am confused between 2 urls : (or any other which is better)

/rest/v1/packageDetails/rootPackage/{packageId}

Or

/rest/v1/packageDetails/{packageId}/rootPackage

what should be the most suitable rest end point url ?

3 Answers

Option 2. To demonstrate reasoning, I will use a different example.

Lets say you have a rest API endpoint:

/rest/v1/users/{userId}

If you wanted to create an additional endpoint to retrieve a subset of data, for example attributes, you would structure it like so:

/rest/v1/users/{userId}/attributes

Another use case to retrieve a specific attribute for a user may look like:

/rest/v1/users/{userId}/attributes/{attributeId}

The important thing to note, is that the attributes belong to the user. The attribute is one or many bits of data that are owned by a specific user.

In your case, a package has-a rootPackage, so you can model rootPackage as belonging to a specific package.

Short answer

REST is an architectural style and not a cookbook for designing URIs. Now, if you want to stick to REST standards, then you should consider hypermedia.

Long answer

Assuming that there's a REST standard for designing URIs for your resources is a misconception: REST doesn't enforce or suggests any URI design.

The URI syntax is defined in the RFC 3986 and this is the document you should consider when designing URIs. As general rule, the path is organized in hierarchical form (with segments separated by /) and can contain non-hierarchical data in the query component (starting with ?).

If I understand your issue correctly, you could simply use /rest/v1/packageDetails/{packageId} to identify a package.

Then use hypermedia to link to other packages. You can provide links in the header or in the response payload. In a JSON payload, for instance, you could have:

{
  "id": "foo",
  "content": {...},
  "_links":{
    "self":{
      "href":"http://localhost:8080/rest/v1/packageDetails/foo"
    },
    "root":{
      "href":"http://localhost:8080/rest/v1/packageDetails/bar"
    },
    "parent":{
      "href":"http://localhost:8080/rest/v1/packageDetails/biz"
    },
    "children":{
      "href":"http://localhost:8080/rest/v1/packageDetails/foo/children"
    }
  }
}

Neither of your options is strictly right. Why:

  1. For option one, /rest/v1/packageDetails/rootPackage/{packageId} would be supposed to be the URI of what will be returned. But the ID on this URI will be that of a child of the resource that will be returned.

  2. For a similar reason, option 2's URI, /rest/v1/packageDetails/{packageId}/rootPackage will suppose that rootPackage is a sub-resource of /rest/v1/packageDetails/{packageId}, which is absurd as we'd be locating a parent under its child.

A third option that I personally would add and recommend is to simply use a search with a client-defined level (in the package hierarchy):

/rest/v1/packageDetails/?childId=packageId&level=0

This would return the top-level package in the tree where packageId is located. I used level=0 as an example of a field indicating the position of the package in its own hierarchy.

With your good understanding of resources, you can choose a more appropriate name or type, but I believe this is a better option.

Related