restarchitecture

Conflicting REST urls


So I'm building a REST api and need to make some urls. The problem is, I'm running into some conflicting paths. For example:

This simplified example shows a problem occurs when an object has id "summary". What is the best way to solve this? From a REST puritan perspective, what should be the solution?

Here's some of my ideas:


Solution

  • The URL structure is not quite right to begin with so it's difficult to solve it in a clean way.

    For the sake of discussion, let's assume <type> is a books resource. So the first URL is fine - you get a book of the given ID:

    GET /books/<id>
    

    However this is not:

    GET /books/summary
    

    Because it's a bespoke URL, which I guess has a use in your application but is not restful. A GET call should return one or more resources. However a "summary" is not a resource, it's a property of a resource and that's why you end up in this situation of having IDs mixed up with book properties.

    So your best option would be to change this URL to something like this:

    GET /books?fields=summary
    

    By default GET /books would return all the resources, while GET /books?fields=<list_of_fields> will return the books but with only the chosen properties.

    That will be similar to your previous URL but without the ID/property conflict, and will also allow you later on to retrieve resources with specific fields (without having to create new custom URLs).

    Edit:

    Regarding the count of books, it's still useful to reason in terms of resources. /books gives you one or more books, but it should not be used for meta-information about the collection, such as count, but also things like "most read book", or "books that start with the letter 'A'", etc. as that will make the resource more and more complex and difficult to maintain.

    Depending on what you want to achieve I think there'd be two solutions:

    1. Create a new resource that manages the collection of books. For example:

      GET /bookcase

    And that will give you information about the collection, for example:

    {
        "count": 1234,
        "most_read": "<isbn>",
        // etc. - any information that might be needed about the book collection
    }
    
    1. Or a search engine. You create a resources such as:

      GET /book_search_engine/?query=

    which would return a search result such as:

    {
        "count": 123,
        "books": [
            // Books that match the query
        ]
    }
    

    then a query like this would give you just the count:

    // Search all the books, but provide only the "count" field
    GET /book_search/?query=*&fields=count
    

    Obviously that's a more involved solution and maybe not necessary for a simple REST API, however it can be useful as it makes it easier to create queries specific to a client.