Search code examples
javarestsingle-page-application

Should REST patch accept multiple entities in a single request body or different requests per entity


I have a question around choosing an approach while designing our REST API.

Our REST API will be consumed by a SPA app (Created in React in case relevant) to add/update an Organization model which looks like following -

Class Organization{
    List<Student> students;
    List<Teacher> teachers;
}

We plan to provide Post and Patch methods for interactions with our API.

For Patch, should we a keep single endpoint which could accept request body like given below where SPA can send either one of the entities be updated.

Approach 1 -

Patch

/api/organization
{
    "students":[],
    "teachers":[]
}

Or should we instead provide two separate endpoints to update the specific entity?

Approach 2 -

/api/organization/students/{id}

/api/organization/teachers/{id}

(Please note that in real scenario there are around 10 such entities)

SPA team is in favor of approach 1 keeping single endpoint which gives them flexibility to send any entity to a single patch endpoint and not having to keep track of different endpoints per entity.

On the other hand, API team is in favor approach 2 of patch endpoint per entity so they can have events generated on the back-end based on the patch call they receive per entity and not having to go through request body to see what came in.

Is there any REST standard which applies in above scenario to choose one approach over the other?


Solution

  • For Patch, should we a keep single endpoint which could accept request body like given below where SPA can send either one of the entities be updated.

    That depends on: what are you using for GET? Do you have one, two, or three resources?

    If you are supporting reads via GET /api/organization, with all of the details of students and teachers embedded in the representation you return, then you should normally want to PATCH the organization resource.

    On the other hand, if GET /api/organization returns a representation that links to data somewhere else (ex /api/organization/students/1), then you should normally target the linked resource that has the representation you wanted to change.

    Remember, you are implementing a facade to make your service look like an HTTP-aware document store. So your endpoints should understand PATCH requests the same way that a document store does: that the patch is intended to be applied to the document identified by the target uri of the request.

    Expressed another way: PATCH really doesn't care whether a resource captures information about a single entity or multiple entities in your database. It's all about the resource (ie: the web page) and making remote authoring changes to the representation(s) of that web page.

    Which is pretty much the whole point of REST's "uniform interface" constraint - all resources understand request messages the same way, regardless of how they are implemented behind the facade.

    The one constraint on PATCH that might impact your choice of resource model:

    The server MUST apply the entire set of changes atomically and never provide (e.g., in response to a GET during this operation) a partially modified representation. -- RFC 5789

    So if patching teachers and students at the same time would require a distributed transaction, then maybe you don't want a resource model that suggests they can be changed together atomically.


    The heuristic to use is pretty simple: how would you arrange this information on web pages?

    If everything were embedded within a single HTML document, then you would of course patch that document. On the other hand, if the main document was linking to other documents, then you would patch the main document to change the links, and patch the link target to change the representations returned from there.


    Does this mean the patch operation - /api/organization, should be executed atomically on the server (for ex. as a transaction on a DB) and if students node in the request has bad data, teachers should not be saved/rolled back?

    If you want a simple answer that elides the concerns of nuance: yes.

    The more complicated version considers this observation by Roy Fielding:

    HTTP does not attempt to require the results of a GET to be safe. What it does is require that the semantics of the operation be safe, and therefore it is a fault of the implementation, not the interface or the user of that interface, if anything happens as a result that causes loss of property....

    If we can apply that idea in general, then a PATCH request means "please apply these changes atomically", but the server does have the freedom to do something other than what was asked.

    From the perspective of the server, these are our resources, and we get to decide when and how to change them. So we could reject the proposed patch, and also make changes of our own choosing, which could be a subset of the changes that were proposed in the request.

    But if we do that, and it "makes a mess", that's on us (the implementation) and not on HTTP or on the client sending the messages.