The canonical way to RESTfully apply a set of changes to a resource is through the use of the HTTP
Although a lot has been said about how to use other HTTP verbs, the community has written comparatively less about
PATCH for probably these two reasons:
- It didn’t make it into the HTTP/1.1 spec. It wasn’t until 2010 that
PATCHwas solidified into an RFC, so many APIs and frameworks had to be updated to accommodate for the newcomer. For example, AngularJS didn’t support it for nearly 4 years!
- The spec goes through a lot of effort defining what to say, but not how to say it.
Table of Contents
The Head-In-Sand Approach To RFC Authorship
A key point in the spec was underscoring the difference between
PUT payloads include a snapshot of the whole resource’s new identity, while
PATCH must contain instructions on how to modify the server’s existing version of the resource.
Side note: Anyone who says
PATCH payloads are supposed to be a snippet of the resource’s modifications is wrong, and apparently also an idiot.
It is expected that different patch document formats will be appropriate for different types of resources…Therefore, there is no single default patch document format that implementations are required to support.
This unopinionated stance was meant to empower the server programmers to implement the most appropriate patch format for each resource type. The idea was that given the freedom to do so, everybody would do it right, every time.
Of course that didn’t happen.
Same Same, But Different
The ambiguity in the spec has led to wildly different (and of course, incompatible) implementations across each server, even when the resource types are identical.
Every blogging CMS API can implement a perfectly RESTful endpoint for updating a blog post with
PATCH, but each one of them will do it an unnecessarily different way because there’s no standard, no best practices that describe a good way to represent atomically updating a resource over HTTP.
What application developers really need is a common way to structure a HTTP
PATCH request. This will pave the way for reducing implementation fragmentation, which will lead to:
- Greater skills transference: easier to switch from one project to another without having to learn more unique implementations.
- Increased certifiability: easier to confirm that the work is correct.
- Better resource allocation: no need to design a new patch format, existing implementations can be reused.
So what would put us on the right track towards more unified HTTP
PATCHes? There’s a few options:
- Use JSON Patch
- Get together and come up with something new
- Re-purpose some existing standard or format
While JSON Patch is an IETF standard specifically designed to be the missing piece of the standards-based puzzle, it has a few issues:
- Its standard is not versioned. Any upgradable technology does badly without versions.
- It doesn’t specify how errors should be communicated outside of HTTP response codes. See HTTP Status Codes Are Not Enough.
- Adoption rate is very low. This means low community critiques, tutorials and support. This also leads to poor tooling.
- The baffling JSON Pointer-based
pathproperty that treats JSON structures like pseudo-URLs instead of regular dot- and square-bracket-based notation.
It seems like continuing with JSON Patch (option 1) as it currently is will not be good enough.
However, coming up with something brand new is a very high-cost task, especially considering the long tail of significant adoption. It’s likely that without the required order of magnitude improvement, we should move onwards from option 2 and decline to build yet another solution from the ground up.
Personally, I believe the case is strong for the community to evaluate the plausibility of re-purposing an existing format. One such option I think is worth investigating is the JS-based Flux Standard Action.
The Case For FSAs
Flux Standard Actions would be a good starting point for a standardised HTTP
PATCH payload for several reasons.
It’s Open Source And Actively Maintained
The spec’s canonical home is on GitHub, where the web community can rally around and contribute meaningful discussion, without needing a position at WHATWG or the IETF.
Since it is actively maintained, problems are rectified quickly and improvements are implemented in short cycles.
The Standard Is Versioned
This increases the strength of the API’s contract and allows developers to sidestep the disadvantages of using non-versioned mutating standards.
It’s A Standard
Though there are pitfalls to designing a standard, the concept still allows for an authority to determine what is correct, and encourage programmers to build their systems in a common way. Roy Fielding actually noted during the development of RFC 5789 that it takes too long for individual entities to come to an agreement on best practice.
Side note: if Github Flavored Markdown is considered
a standard, then FSA’s spec is too.
It’s Already Popular
FSAs are the de-facto method of dispatching requests to change a resource in React-land.
And, the number of React users grows, the FSA community gains a lot of support, resources and more.
The spec is very small and requires only a few minutes to read the entire thing. Compare it with RFC 5789, it’s associated errata and other supplementary resources (including the mandatory RFC 6902) and you’ll find that gravitating towards the simple option is preferable.
The Tooling Is Better
There already exists a number of resources for working with FSAs quickly and efficiently. This lets the community leverage the best work and help get things done more effectively.
The Payload Scales Both Ways
Very tiny instructions need only one property:
type. This means that if the server knows what to do with a resource given very simple instructions, the client can send minimal data.
On the other hand if you need a very complicated
payload field can be as large as is appropriate for your task.
Errors Are A First-Class Concept
Most of an API’s code goes to handling errors because there’s only one successful path, and a basically unlimited number of error paths.
Incidentally, this is the reason why headphones spend more time tangled than straight.
FSAs make sure that any client consuming your API will always know when an error occurs, and will get good information to debug it. Combine this with a great error standard and any developer consuming your API will almost enjoy receiving errors.
Since incompatible implementations and fragmentation really sucks, the web community needs to gather its collective will and wisdom and move towards unified, common ways to do things.
The more we do the same stuff the same way, the better we’ll all be for it. Using Flux Standard Actions as the payload in HTTP
PATCH requests could be the right way to go.