user3216673 user3216673 - 1 month ago 14
reST (reStructuredText) Question

REST API - design consideration

I've got a question about designing REST API. Consider the following situation: we've got table called

banners
and table called
images
. Each banner has got one image and each image belongs to one banner (table images is used to store another images, not only banners, so joining the tables is not the solution).

table Banner table Images
________________________ ______________________
| id | Int | | id | Int |
| title | VARCHAR | | filename | VARCHAR|
|__________|___________| | banner_id | Int |
| article_id| Int |
|___________|________|


I've read some articles about creating REST APIs and according them, I should make this URIs for data retrieving:

1) api/banner/1
2) api/banner/1/image


But I will always need an image with banner, so why is not better to return everything by calling first API route? If I'll do it by this way (two routes), how should I implement the calls from frontend? Should I write two
http.get()
methods for retrieving banner first and then its associated image? Thanks for answers!

Answer

There are a few options for you in this situation:

Offer Both Resources

As you noted, if you offer both resources, you would have to do two GET requests to retrieve all the data you need.

Offer Both Resources, and Embed the Image in the Banner

You can do both - api/banner/1/image can return data about the image, and api/banner/1 can return data about the banner, with the image embedded.

If you use a media type such as HAL it would be considered an 'embedded' resource:

{
    "id": 1,
    "title": "banner title",
    "_embedded": {
        "image" : {
            "id": 1,
            "filename": "some path",
            "_links": {
                "self": {
                    "href": "api/banner/1/image"
                }
            }
        }
    },
    "_links": {
        "self": {
            "href": "/api/banner/1"
        }
    }
}

This way you could get all the data you need with a single GET.

Only Offer the Banner Resource

There is no rule that says your database tables have to line up exactly with your API resources.

There's nothing wrong with only offering api/banner/1 and having it return something like:

{
    "id": 1,
    "title": "banner title",
    "imageFileName": "some path"
}

The fact that you happen to store the data fields on separate tables internally in your system is just an implementation detail/

Don't forget Non-GET methods

Although you are currently focussing on the GET method, your resource structure should also take into account the non-GET methods you want to offer, which means you should consider other operations, such as create, update and delete. This will help determine which of the above operations to offer - e.g.

  1. Do you ever create a banner without an image?
    1. If you do, you should offer both resources. But you could still embed the image resource if it exists, to save the second GET request.
    2. If you don't, then there's no problem just offering the banner resource - from the client's perspective, they should never consider the banner without an image
  2. How often do you update the image without updating other properties of the banner?
    1. If the answer is frequently, then it could be helpful to offer the image resource - but again, you could still embed the resource to save the second GET request

Suggestion on your Data Structure

You mention that the image might be used for other types of images, but that a banner could only have one image. If that is the case, I'd suggest reversing the direction of the relationship, e.g.:

table Banner                    table Images
________________________        ______________________
| id       | Int       |        | id        | Int    |
| title    | VARCHAR   |        | filename  | VARCHAR|
| image_id | Int       |        |___________|________|
|__________|___________|

Otherwise, how would you handle it if two records in the Image table had the same banner_id?