Bailey Parker
Bailey Parker

Reputation: 15903

RESTfully handling sub-resources

I've been creating a RESTful application and am undecided over how I should handle requests that don't return all entities of a resource or return multiple resources (a GET /resource/all request). Please allow me a few moments to setup the situation (I'll try to generalize this as much as possible so it can apply to others besides me):

Let's say I'm creating a product API. For simplicity, let's say it returns JSON (after the proper accept headers are sent). Products can be accessed at /product/[id]. Products have reviews which can be accessed at /products/[id]/review/[id].

My first question lies in this sub-resource pattern. Since you may not always want the reviews when you GET a product, they are accessible by another URI. From what I read I should include the URI of the request that will return all review URI's for a product in the response for a product request. How should I go about this so that it abides to RESTful standards? Should it be a header like Reviews-URI: /product/123/review/all or should I include the URL in the response body like so:

{ 'name': 'Shamwow',
  'price': '$14.99',
  'reviews': '/product/123/review/all'
}

My second question is about how the /product/[id]/review/all request should function. I've heard that I should just send the URL's of all of the reviews and make the user GET each of them instead of packaging all of them into one request. How should I indicate this array of review URIs according to RESTful standards? Should I use a header or list the URIs in the response body like so:

{ 'reviews': [ '/product/123/review/1',
               '/product/123/review/2',
               '/product/123/review/3'
             ]
}

Upvotes: 5

Views: 16869

Answers (3)

cloudfeet
cloudfeet

Reputation: 12891

The JSON Schema standard might help you here, in particular Hyper-Schemas.

It lets you define how to extract link URIs from your data, and what their "rel"s are - essentially turning your JSON data into hyper-media. So for your first bit of data, you might write a schema like:

{
    "title": "Product",
    "type": "object",
    "properties": {...},
    "links": [
        {"rel": "reviews", "href": "{reviews}"}
    ]
}

The value of href is a URI Template - so for example, if your data included productId, then you could replace the value of href with "/product/{productId}/review/all".

For the second bit of example data (the list of reviews) you might have a schema like this:

{
    "type": "object",
    "properties": {
        "reviews": {
            "type": "array",
            "items": {
                "links": [
                    {"rel": "full", "href": "{$}"}
                ]
            }
        }
    }
}

In the URI Template of href, the special value of {$} means "the value of the JSON node itself". So that Hyper-Schema specifies that each item in the reviews array should be replaced with the data at the specified URL (rel="full").

Upvotes: 1

fumanchu
fumanchu

Reputation: 14559

As to your first question (header or body), definitely do not invent your own custom header. Some here will argue that you should use the Link header, but I think you'll find plenty of need for nested links and should keep them in the body.

How you indicate either the URI to the reviews/ resource, or the list of URI's within that, is entirely up to the media type you select to represent each resource. If you're using HTML, for example, you can use an anchor tag. If you're using plain JSON, which has no hypermedia syntax, you'll have to spend some time in the documentation for your API describing which values are URI's, either by nominating them with special keys, or wrapping them in special syntax like {"link": "reviews/123"}, or with a related schema document.

Take a look at Shoji, a JSON-based media type which was designed explicitly for this pattern of subresources.

Upvotes: 1

Will Hartung
Will Hartung

Reputation: 118784

Your problem is you're not using Hypermedia. Hypermedia specifically has elements that hold links to other things.

You should consider HAL, as this is a Hypermedia content type that happens to also be in JSON.

Then you can leverage the links within HAL to provide references to your reviews.

Upvotes: 8

Related Questions