Suppose I'm designing a REST API and I need the clients to be able to obtain files with metadata. What is a good way to design the resources / operations?
Some ideas come to mind:
A single resource (i.e. GET /files/{fileId}), which returns a multi-part response containing both the file and a JSON/XML structure with metadata. I have a feeling that this is not a very good approach. For example, you cannot use the Accept header for the clients to determine if they want a XML or a JSON metadata representation, since the response type would be multi-part in both cases.
Two resources (i.e. GET /files/{fileId} and GET /files/{fileId}/metadata), where the first one returns the file itself and the second one a JSON/XML structure with metadata. There can be a link from the metadata to the file. However, how do I send a link to the metadata along with the file?
I would suggest using the second idea you presented. This is the strategy used by most of the major web drives (Box, Dropbox, Google Drive, etc). They often have a significantly different URL because they store content and metadata in disparate locations.
You can add a Link header to the file response with a link to the metadata. Link headers are described in RFC 5988. The set of currently-registered link relations is here. Off the cuff, it seems that the describedBy
relation is appropriate here.
I've had success with the following kind of API design. This differs slightly from what you suggested in that the main resource just contains links to its components.
POST /file
Request
<bytes of file>
Response
Location: /file/17
{
"id": 17
}
GET /file/17
{
"data": "/file/data/17",
"metadata": "/file/metadata/17"
}
GET /file/data/17
<bytes of file>
GET /file/metadata/17
{
"type": "image",
"format": "png"
}
DELETE /file/17
Your first Option is not at all a good choice because it violates following REST constraint.
Manipulation of resources through these representations under Uniform interface Principle.
When a client holds a representation of a resource, including any
metadata attached, it has enough information to modify or delete the resource.
If you brake it. Your URL will not be consider as RESTful.
Wiki about it.