Search code examples
restrestful-architecture

Do I violate REST best practices when I use more than one value on my endpoint?


I'm more or less new to REST and right now I have the case where I don't know if this is right or wrong what I'm doing. As far as I know, there are no strict rules in the REST world and I would like to hear one or two opinions from you.

I have the following resource: http://localhost:80/srv1/public/api/v1/folders/

With this endpoint I get the information for a given folder. Like for example:

GET: http://localhost:80/srv1/public/api/v1/folders/vacations

The result looks like this:

Name       | Typ
---------- | ------
2017 Maui  | Folder
2016 Japan | Folder

Now I want the information of 2016 Japan and I programmed that my endpoint is able to receive multiple values like so:

http://localhost:80/srv1/public/api/v1/folders/vacations/2016 Japan

The question is: Is this false because I use more than one value/parameter for my endpoint?

Background: I need to retain the structure of the folders the user has clicked. E.g. /vacations/2016 Japan/Tokio to process it further on my server/backend. Because I don't see another way of achieving this I would like to hear your option. Thank you.


Solution

  • As far as I know, there are no strict rules in the REST world

    Right; REST doesn't care what spelling you use for resource identifiers. From the point of view of clients, the identifiers are opaque. The server can encode information into them at its own discretion and for its own exclusive use.

    But a good rule of thumb is to consider what things would look like as a 1990s website.

    You would click on a link labeled folders, and that would GET you a representation of those folders, including an entry labeled "vacations". Clicking that link would GET you another representation, that would include a link labeled "2016 Japan". Clicking that link would GET you a representation of that, and so on.

    The values in the HREF attributes of the links could be anything, because you are just clicking on them.

    "folders" : { "href" : "/28484a30-ccf7-4b36-8f1b-cea70223d4f7" }
    "vacations" : { "href" : "/2abaac1b-5bb8-4284-abb6-37953cac68b1" }
    "2016 Japan" : { "href" : "/84dfc3c2-3d04-4b33-9551-cb5a35237de5" }
    

    Back when dinosaurs roamed the web, we were frequently dealing with static, hierarchical web sites. Using relative references allowed the reuse of representations at different points in the URI space - the client could follow the standard resolution rules to compute the intended identifier.

    So you might see spellings like

    "folders" : { "href" : "/folders" }
    "vacations" : { "href" : "/folders/vacations" }
    "2016 Japan" : { "href" : "/folders/vacations/2016%20Japan" }
    

    %20 because the SP in the identifier needs to be percent encoded

    Background: I need to retain the structure of the folders the user has clicked. E.g. /vacations/2016 Japan/Tokio to process it further on my server/backend. Because I don't see another way of achieving this I would like to hear your option.

    That's a bit twitchy. The REST architectural style uses Client Stateless Server hierarchical style. This means that there is no session state on the server; the client is just sending links.

    What this means is that when the server receives a request for /folders/vacations/2016%20Japan, it can't know that the client previously visited /folders and /folders/vacations. For example, I might be following a link that you sent to me in an email.

    Note: there's nothing wrong with composing URI this way; the server can encode information into the uri any way it wants. You just need to be careful about what assumptions you make about client state.

    That said, if you don't intend a hierarchical structure, then path segments may not be your best choice

    The path component contains data, usually organized in hierarchical form

    Non hierarchical data is normally handled in one of two ways; either by encoding it into the query component

    "folders" : { "href" : "/?folders" }
    "vacations" : { "href" : "/?folders,vacations" }
    "2016 Japan" : { "href" : "/?folders,vacations,2016%20Japan" }
    

    or by encoding it into an individual path segment

    "folders" : { "href" : "/folders" }
    "vacations" : { "href" : "/folders,vacations" }
    "2016 Japan" : { "href" : "/folders,vacations,2016%20Japan" }
    

    In RESTFul Web Services, Ruby and Richardson proposed using punctuation to delimit data at the same level in the hierarchy; commas if the order is significant, semi-colons if not.

    Note that there is no rule that the data in your collection needs to go on into the last path segment.

    "folders" : { "href" : "/folders/pages" }
    "vacations" : { "href" : "/folders,vacations/pages" }
    "2016 Japan" : { "href" : "/folders,vacations,2016%20Japan/pages" }
    

    RFC 6570 defines variable expansions; access to a URI Template library with support for level 4 templates makes these spellings more practical.