I am looking for some advice in regards of best practices to build a HTTP PATCH request that can edit multiple entities in one request. The reason I am asking is because to me Rest API is quite vague and I don't have much experience building Rest APIs.
My approach would be to create a request with this data:
[
{
id:<entity id to update>,
patch:
{
op: <patch operation>,
path: <field to update>,
value: <new value>
}
},
...
]
What do you think and what would you recommend based on your experience?
thank you very much
2 Answers 2
I am looking for some advice in regards of best practices to build a HTTP PATCH request that can edit multiple entities in one request.
RFC 6902 , describes JSON Patch, and serves as a pretty good reference for how you might design a patch document.
Fundamentally, the patch document is a representation of a change set, where each entry describes a change (or test) to be made. In the case of JSON patch, the "entities" are nodes in a document, with descriptions of the operations to be performed on each node.
So in your patch document specification, you would define how the representation encodes the identities to be changed, which change operations are allowed, how the arguments are specified, and so on.
A thing to keep in mind with multiple entities: RFC 5789 is very clear that the semantics of PATCH are all or nothing
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. If the entire patch document cannot be successfully applied, then the server MUST NOT apply any of the changes.
If something unfortunate or expensive happens because of a partially applied patch, the responsibility for the error clearly lies with the server.
What this will normally mean is that a patch should only be changing entities that are within the same consistency boundary (for example, they are all part of the same physical database, so the server can put all the changes in one transaction; or they are all part of a single document, so the server can edit a local copy of the document and then replace the original).
If the server can't guarantee those consistency constraints, it should not be supporting the PATCH method.
Your structure works, and all that's requested to PATCH
is to be idempotent - you need to lock all resources, possibly one id at a time. This also may require that you first gather and deduplicate all the items in the array, in case an id
is specified twice.
When you do all this, patching one resource or more than one is essentially the same thing. Actually you could check whether the payload is an array of dictionaries or a dictionary, and if the latter, transform it in an array of one dictionary, then proceed.
To save some space (not really a good practice since you're adding complexity) you can guess the significance of missing fields:
- op field is missing, but path and value are present: this is an update/add
- op and values are both missing: this is a field removal
You could also allow for id to be an array, meaning that an operation is to be repeated on several resources.
The problem lies in handling errors and exceptions. What do you do if one patch fails? Do you wrap the whole operation inside a transaction and rollback? Do you report an array of return codes?
200 (nothing returned) All patches OK
500 { 200: [ { 17: "OK", 29: "OK", 35: "OK" ], 500: [ { 22: "No such field" } ] }