Designing rest api for nested resources

Viewed 644

I have the following resources in my system 1. Services 2. Features where a feature has the following JSON structure,

{
 id: "featureName",
 state: "active",
 allowList: [serviceID1, serviceID2],
 denyList: [serviceID3, serviceID4]
}

I am trying to update the allowList or denyList which consists of serviceIDs and thinking of using PATCH method to do it like below,

/features/{featureId}/allowlist 
/features/{featureId}/denylist 
/features/{featureName}/state/{state}

My first question is should I even include allowlist, state, denylist in the url as my resources are services and features, not the allowlist or denylist.

How should the rest endpoint look like?
After reading thread mentioned below I was thinking about restructuring urls as below,

/features/{featureId}

[
    { "op": "add", "path": "/allowList", "value": [ "serviceA", "serviceB"]},
    { "op": "update", "path": "/state", "value": false}
]

Lastly, the use of PATCH even justified here? or there is any better way to design the api.

Note: I have got some help from the thread REST design for update/add/delete item from a list of subresources but have not used patch often.

1 Answers

How should the rest endpoint look like?

The URI that you use to edit (PUT, PATCH) a resource should look the same as the URI that you use to read (GET) the resource. The motivation for this design is cache-invalidation; your successful writes automatically invalidate previously cached reads of the same resource (same URI).

Lastly, the use of PATCH even justified here? or there is any better way to design the api.

In this example, the representation of the document is small compared to the HTTP headers, and the size of your patch document is close to the size of the resource representation. If that's the typical case, I'd be inclined to use PUT rather than PATCH. PUT has idempotent semantics, which general purpose components can take advantage of (for example, automatically resending requests when the response to an earlier request has been lost on the network).


GET /features/1 by user1 
PUT /features/1 //done by user 2 
PUT /features/1 //done by user1 

the PUT by user2 will not be visible for user1 and user1 will make an update on the old object's state (with id=1) what can be done in this situation?

Conditional Requests.

You arrange things such that (a) the GET request from the server includes validators that identify the representation (b) the server responds 428 Precondition Required when the request lacks conditional headers (c) the clients know to read the validators from the resource metadata, and use the correct condition headers when submitting the PUT request (d) the server knows to compare the validator to the current representation before accepting the new representation.

Related