Question

We are developing a REST API that serves as a backend for our iOS and Android apps as well as an AngularJS web app. In order to optimize performance, we have to provide images in a variety of resolutions. I am looking for guidance around how to provide the client with the correct image URL for its device resolution. I can imagine three possibilities:

1. The client has logic to determine the resolution dependent URL for an image.
The REST API returns a canonical image URL:

{
   "user": {
      "id": 1,
      "image_profile": "https://cdn.mydomain.com/abcd.jpg"
   }
}

The client then knows how to change the URL to get the needed resolution.
E.g. something like: https://cdn.mydomain.com/abcd@2x.jpg or https://cdn.mydomain.com/w_100,h_100/abcd.jpg.

This is based on the idea, that the client knows exactly where the image will go and in what size and resolution it is needed. The cons are more logic on the client. This could for example be implemented with a service such as http://cloudinary.com/.

2. The server provides different versions for each image.
The REST API returns all available image URLs:

{
   "user": {
      "id": 1,
      "image_profile": {
         "url": "https://cdn.mydomain.com/abcd.jpg",
         "versions": {
            "mhdpi": "https://cdn.mydomain.com/abcd_mhdpi.jpg",
            "lhdpi": "https://cdn.mydomain.com/abcd_lhdpi.jpg",
            "2x": "https://cdn.mydomain.com/abcd@2x.jpg",
            "web": "https://cdn.mydomain.com/abcd_web.jpg"
         }
      }
   }
}

In this solution the client needs less logic and the implementation of resizing the images is independent of the client. Responses become a bit polluted.

3. The server returns the right image automatically based on the user agent (or any other parameter)
The client could specify its expected resolution in a user agent header (or could append something like ?resolution=2x to every request.
For an example user agent of iPhone 5S (iOS 7.1) the API would automatically return the right image:

{
   "user": {
      "id": 1,
      "image_profile": "https://cdn.mydomain.com/abcd@2x.jpg"
   }
}

The client is oblivious to the resolution problem but this approach makes responses less cacheable and feels the most like magic.

Can you please suggest other solutions, elaborate on the pros and cons of the ones presented and point me to some resources about how the well-known APIs handle this problem?

Was it helpful?

Solution

The second option fits closest with a RESTful API design, with the inherent benefits that come with it.

Taking each in turn:

1. Client altering the URL has the risk that you'll break the clients if you ever need to change the image identifier URL format for any reason.

2. Server provides multiple versions is best aligned with a RESTful approach, with the principle benefit that changing the URL format will not break existing clients. It also allows for extensibility which is potentially self descriptive and machine readable (with a small change) like this:

{
   "user": {
      "id": 1,
      "image_profile": {
         "url": "https://cdn.mydomain.com/abcd.jpg",
         "versions": {
            "100": "https://cdn.mydomain.com/abcd_mhdpi.jpg",
            "150": "https://cdn.mydomain.com/abcd_lhdpi.jpg",
            "300": "https://cdn.mydomain.com/abcd@2x.jpg",
            "72": "https://cdn.mydomain.com/abcd_web.jpg"
         }
      }
   }
}

...i.e. you could redefine the identifier as a "DPI" figure or something similar. I don't know how advanced your client applications are; but potentially they could look for the numerical "nearest match" of DPI for the screen size in use. You could then insert additional resolutions in future accordingly.

3. Server uses agent string avoids the risks of option 1; but the client application itself is best placed to make the decision on resolution because it knows more about the context.

Summary

Option 2 doesn't restrict you in any way; and is also the most resilient to avoiding breaking changes in future.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top