1

Let's say that I have a custom database contacts, and there are two tables inside:

contacts
  - user
  - group

A user may belong to many group, and a group can have multiple user. If I add/update/remove a user into the database, group should be updated too (if the user belongs to any of the group). How should I implement the REST API? Currently, I have two different implementation:

Single End Point

Build a PUT /user endpoint, and let the backend code do all the work in a single end point. ( Check validity, update the user, update all the group related to the user )

Multiple End Point

Build many single-purpose endpoint, and let the front-end javascript decide how to send the ajax requests. Perhaps:

PUT /user 
PUT /group 

The first method duplicates many codes, and the second method may cause error if some requests did't send to the backend properly. Another question is that should the REST API always make sure that the DB data's integrity stays correct, or we could separate the whole action into multiple requests? Thanks in advance!

  • 4
    How should I implement the REST API? How do you want the API to be consumed? – Laiv Jul 17 '17 at 12:27
  • Speaking from personal experience as a developer of REST APIs consumed by mobile applications, you really do not want to go with multiple operations per request. Make the operations simple, single. Having a large endpoint makes it extremely difficult to revert some action should something gone wrong. – Andy Jul 17 '17 at 13:55
  • @Laiv The API should be called mostly through ajax request by the web browser and there is no plan to do the mobile application just yet. – Wayne Chang Jul 17 '17 at 15:04
2

As @Laiv states in his comment you should think about how you want it to be consumed. How does the user of the API want this to work? Will it on the other side of the API be more beneficial to perform one or multiple actions to do this?

We cannot speak for what is best in your case.

With that said though I typically prefer the single endpoint taking care of these actions in one fell swoop. This to reduce the amount of requests being made as your validations, code and database updates typically are cheaper for these actions than the round trip made to and back from the server. It really boils down to if you want to reduce latency at the expense of, what appears to from your question, some code complexity or is the maintainability of your code more important? There's obviously some other factors here but I think you're catching my drift.

In addition, nothing prevents you from implementing both cases if you can find two optimal use cases for both of them in different situations though you will need to document their differing use cases clearly and in a way that's easy to understand.

  • Even HTTP v1.1, the de facto standard for today, caches connections. Multiple requests to the server are not a problem. – Andy Jul 17 '17 at 14:26
1

Many things can go wrong between client and server. I would always make sure that one request can never put the DB in some erroneous state. Thus: if group needs to be changed upon a PUT /user, do so. Don't assume the client will be able to request the PUT /group as well!

The result of a request should always be atomic.

0

Another way to think of this is the idea of a more formal notion of multiple commands in one request, rather than more-or-less hard coding this on /user. Thus, you'd have the primitives, /user and /group, but also a way of making an extended request that covers updates to both.

With REST we get our mindset stuck in a mode of CRUD thinking, which sometimes leads us solving problems with one-off hacks instead of raising the level of abstraction.

As a more formalized alternative, there is an extension, OData, which offers a standardized way of providing (missing or otherwise un-standardized) features on top of REST's CRUD-oriented resource end points.

For one, these missing features include joins for queries, which means that the client doesn't have to make multiple request for inquiries that span different resources. For another, OData includes being able to package multiple update commands in a single request (that perhaps all succeed or all fail). OData provides a thought out and standardized syntax for representing these things ( plus there are some libraries available).

In the general CRUD — like any basic capability — handles a large number of use cases without extension, though certain application domain use-cases simply require that the client accomplish joins and/or transactions.

I can certainly appreciate that OData may be overkill for this one question alone, though I'd encourage you to be aware of this as a way of raising the level of abstraction we're dealing with.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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