2

I have a Spring Boot REST API that will copy content from one Amazon S3 bucket to another. The source and destination buckets are specified in the body of a POST request sent to the API. This works fine and the endpoint is something along the lines of

/api/v1/copy-stuff

The request body looks something like this

{
 "sourceBucket": "blah1", 
 "targetBucket": "blah2"
}

A new request has come in to enhance the feature so that it will move content instead of copying it; i.e.: after copying content from source to destination, it will delete the source content.

My instinct is that this could be achieved most easily by just adding a Boolean variable to the request body, which if true will result in files being moved instead of copied.

But I’m wondering if that’s a sound design. Would it be better in terms of code readability and structural soundness to have a separate API that, while sharing some code with the copy API, moves the files? In other words, would it make sense to have two endpoints, like this?

/api/v1/copy-stuff
/api/v1/move-stuff

I can see advantages and disadvantages for both options but I’d be curious to hear any opinions.

asked Aug 13, 2024 at 20:55

1 Answer 1

4

It helps to think about this feature from the perspective of the clients of your API. What do they expect? In a situation like this, I believe Principle of Least Astonishment provides the best guidance. Don't do something that would surprise the clients of your web API. Do the thing they would expect.

What clients expect can be very contextual. I would look to the meanings of "copy" and "move" to derive what clients expect. Copying something implies that the source information gets duplicated. You can find it in the old location as well as the new location. Moving something implies it no longer exists at the source, and from now on only exists at the destination.

The challenge is how the original web API was named: /api/v1/copy-stuff

So, let's think through idea #1, which is to pass some sort of boolean flag. How would that look to clients?

  • POST /api/v1/copy-stuff (copies stuff)

  • POST /api/v1/copy-stuff?move=true (moves stuff)

  • POST /api/v1/copy-stuff?deleteFromSource=true (copies and then deletes stuff, so basically it "moves" stuff)

  • Pass boolean property in the JSON body:

    POST /api/v1/copy-stuff
    {
     "sourceBucket": "...",
     "targetBucket": "...",
     "move": true
    }
    

    Or:

    POST /api/v1/copy-stuff
    {
     "sourceBucket": "...",
     "targetBucket": "...",
     "deleteFromSource": true
    }
    

What would you expect if you were calling this web API? Does it feel natural? Does this change in behavior feel cohesive with the old behavior? What happens if I omit the new property? What is the default behavior?

Those are the questions I ask myself when making these sorts of decisions. Clients will likely have the same questions. You would need to document this information and give it to clients somehow, which complicates the implementation of this feature.

Now, let's say you create a new API:

POST /api/v1/move-stuff
{
 "sourceBucket": "...",
 "targetBucket": "..."
}

Well, I suppose there's nothing to say here. It's a new endpoint. It says it moves stuff, and by golly that's what it does. Don't be surprised if the source bucket reports that the thing you moved doesn't exist anymore. You also wouldn't be surprised if the thing you moved only exists in the target bucket. Since this is a new API endpoint, clients would expect the old endpoint to behave just as it used to. No additional overhead is necessary to communicate this change, because the way things are named conveys to clients how they should be used.

While your question is about web APIs, I encourage you to read Is it wrong to use a boolean parameter to determine behavior? It focuses on method calls rather than HTTP requests, but it is conceptually very similar to your current situation.

answered Aug 13, 2024 at 21:23
1
  • That’s an excellent and thoughtful response, thank you. Commented Aug 13, 2024 at 21:35

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.