3

I am designing a HTTP-based REST API. Let's say I have an entity called Entity that has a bunch of properties. Some of its properties are files. Let's say Entity has following properties:

name: string
description: string
photos: array of photos
videos: array of videos

API is designed to be used from mobile devices and should work well under conditions of slow or unstable connection. The thing is the object should be not considered as complete until I upload all the resources the client have.

What it the best way to construct a new object?


For now I come up with the following solution. Add readiness flag isReady, first post basic object data within single json:

POST /entities/ {name: "somename", description: "description", isReady: false}
obtain id of newly created `entityId`

Then upload resources one by one:

POST /entities/{entityId}/photos/ <photo data>
POST /entities/{entityId}/videos/ <video data>

And then update object's readiness flag

PUT /entities/{entityId}/ {isReady: true}

The second solution that comes to mind is to create separate endpoints for photos, videos. Then I'll be able to first post photos and videos and then create Entity with references to resources.

POST /photos <photo data>
obtain ids
POST /videos <video data>
obtain ids

POST /entities/ {name: "somename", description: "description", photos: ids[], videos:ids[]}

The question with the second solution: is it okay for resource to be referenced by multiple URIs?

/entities/photos/{photoId}
/photos/{photoId}

Is the first solution correct? Wouldn't the second one be overcomplicated?

Thanks in advance

1

1 Answer 1

2

I have successfully used both patterns; and both will work fine. I wouldn't say that either is more complicated than the other. One thing that you might also consider, for the first pattern, is to include in your entity description a "promise" to fulfill. For example, you might have a JSON object that enumerates the data you'll be providing:

photos_promise: {
    expect: 5,
    checksums: [..., ..., ..., ..., ...]
}

Then, when you upload the five photos, you can do an additional validation to ensure that the photo file you've received matches one of the provided checksums. When you've received five photos and they all match, you can have the service automatically "enable" your Entity resource. You can take it a step further and have "partial states" for these objects, such that when you get this entity after having posted three photos, you'd get:

photos: [{url: ..., ...}, ...],
photos_promise: {
    received: 3,
    expect: 2,
    checksums: [..., ...] 
}

This obviously does add complication, but it's also rather elegant.

5
  • After thinking I don't really like an idea with promises and my isReady flag. That approaches add extra parameters to store and process that may impede further system evolution. Thanks! Commented Apr 21, 2014 at 18:48
  • At this point I tend to decouple my APIs for each type of resources. There is a question comes: is it ok for REST API to have a resources e.g. photos and use /photos/ endpoint to work with photos and at the same time be able reference photos with /entities/{entityId}/photos/{photoId} URI? Should the resource be referenced by different endpoints or it is better to use global /photos/ endpoint rather than both /photos/ and /entity/{entityId}/photos/? Commented Apr 21, 2014 at 18:50
  • The one flaw I can see without promises is that dangling resources can appear when resources uploaded and entity is not created for some reason. Commented Apr 21, 2014 at 18:57
  • 1
    If it's a concern that you have dangling resources, add a scheduled task to clean them up. That's not really a big deal.
    – asthasr
    Commented Apr 21, 2014 at 23:21
  • dangling objects it not a concern. Just was sharing my thoughts. Commented Apr 22, 2014 at 20:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.