⚠️ This content has been written a long time ago. As such, it might not reflect my current thoughts anymore. I keep this page online because it might still contain valid information.
Please. Don't Patch Like That.
Clermont-Fd Area, France2019-12-20 // The title of this article has been edited. It should have been edited a long time ago. Then again, sorry about that!
2016-08-06 // Since I wrote this blog post, RFC
7396, introducing the JSON Merge
Patch format, has been created. It can be seen as the “just send what
you need” format. Therefore, it is valid to only send what you need to
update as the [description of changes]
as far as it complies with the
JSON Merge Patch format.
I do apologize for the misuse of the word “idiot”. I did not want to be rude. The exact same word in French is less “strong” than in English.
Modifying HTTP resources is not a new topic. Most of the existing HTTP or REST
APIs provide a way to modify resources. They often provide such a feature by
using the PUT
method on the resource, asking clients to send the entire
resource with the updated values, but that requires a recent GET
on its
resource, and a way to not miss updates between this GET
call, and the PUT
one. Indeed, one may update values before you, and it can lead to bad side
effects. Moreover, sending a complete resource representation utilizes more
bandwidth, and sometimes it must be taken into account. Also, most of the time
you want to update one or two values in a resource, not everything, so the PUT
method is probably not the right solution for partial update, which is the term
used to describe such a use case.
Another solution is to expose the resource’s properties you want to make
editable, and use the PUT
method to send an updated value. In the example
below, the email
property of user 123
is exposed:
PUT /users/123/email
new.email@example.org
While it makes things clear, and it looks like a nice way to decide what to
expose and what not to expose, this solution introduces a lot of complexity
into your API (more actions in the controllers, routing definition,
documentation, etc.). However, it is REST compliant, and a not-so-bad solution,
but there is a better alternative: PATCH
.
PATCH
is an HTTP method (a.k.a. verb) which has been described in RFC
5789. The initial idea was to propose a
new way to modify existing HTTP resources. The biggest issue with this method is
that people often misunderstand its usage. No, PATCH
is not strictly about
sending an updated value, rather than the entire resource as described in the
first paragraph of this article. Please, avoid doing this. This is not
strictly correct:
PATCH /users/123
{ "email": "new.email@example.org" }
And, this is not correct either:
PATCH /users/123?email=new.email@example.org
The PATCH
method requests that a set of changes, described in the request
entity, must be applied to the resource identified by the request’s URI. This
set contains instructions describing how a resource currently residing on
the origin server should be modified to produce a new version. You can think of
this as a diff:
PATCH /users/123
[description of changes]
The entire set of changes must be applied atomically, and the API must never
provide a partially modified representation by the way. It is worth mentioning
that the request entity to PATCH
is of a different content-type than the
resource that is being modified. You have to use a media type that defines
semantics for PATCH, otherwise you lose the advantage of this method, and you
can use either PUT
or POST
. From the RFC:
The difference between the PUT and PATCH requests is reflected in the way the server processes the enclosed entity to modify the resource identified by the Request-URI. In a PUT request, the enclosed entity is considered to be a modified version of the resource stored on the origin server, and the client is requesting that the stored version be replaced. With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version. The PATCH method affects the resource identified by the Request-URI, and it also MAY have side effects on other resources; i.e., new resources may be created, or existing ones modified, by the application of a PATCH.
You can use whatever format you want as [description of changes]
, as far as its
semantics is well-defined. That is why using PATCH
to send updated values only
is not suitable.
RFC 6902 defines a JSON document
structure for expressing a sequence of operations to apply to a JSON
document, suitable for use with the PATCH
method. Here is how it looks like:
[
{ "op": "test", "path": "/a/b/c", "value": "foo" },
{ "op": "remove", "path": "/a/b/c" },
{ "op": "add", "path": "/a/b/c", "value": ["foo", "bar"] },
{ "op": "replace", "path": "/a/b/c", "value": 42 },
{ "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
{ "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
]
It relies on JSON Pointers, described in RFC 6901, to identify specific values in a JSON document, i.e. in a HTTP resource representation.
Modifying the email of the user 123
by applying the PATCH
method to its JSON
representation looks like this:
PATCH /users/123
[
{ "op": "replace", "path": "/email", "value": "new.email@example.org" }
]
So readable, and expressive! Wonderful ♥ This is how the PATCH
method MUST be used. If it succeeds, you get a 200
response.
For XML aficionados, RFC 5261 describes an XML patch framework utilizing XML Path language (XPath) selectors to update an existing XML document.
As of late 2014 (that is, after the publication of this article), a new
RFC introducing the JSON Merge Patch
format and describing another way to send a set of changes has been proposed. It
is very similar to the idea of sending only what needs to be updated, but it is
explicit thanks to the application/merge-patch+json
content type.
To sum up, the PATCH
method is not a replacement for the POST
or PUT
methods. It applies a delta (diff) rather than replacing the entire resource.
The request entity to PATCH
is of a different content-type than the
resource that is being modified. Instead of being an entire resource
representation, it is a resource that describes changes to apply on a resource.
Now, please, either don’t use the PATCH
method, or use it the right way!
It is worth mentioning that PATCH
is not really designed for truly RESTful APIs,
as Fielding’s dissertation does not define any way to partially modify
resources. But, Roy Fielding himself said that PATCH was something he created
for the initial HTTP/1.1 proposal because partial PUT is never RESTful. Sure
you are not transferring a complete representation, but REST does not
require representations to be complete anyway.
Useful Links
- An Extensible Markup Language (XML) Patch Operations Framework Utilizing XML Path Language (XPath) Selectors
- PATCH Method for HTTP
- JavaScript Object Notation (JSON) Pointer
- JavaScript Object Notation (JSON) Patch
- Why PATCH is Good for Your HTTP API
- REST Partial Updates: Use POST, PUT or PATCH?
- Embrace, Extend then Innovate
- Why isn’t HTTP PUT allowed to do partial updates in a REST API?
- The Right Way to Do REST Updates
- HTTP PUT, PATCH or POST - Partial updates or full replacement?
- PUT vs PATCH vs JSON-PATCH
Feel free to fork and edit this post if you find a typo, thank you so much! This post is licensed under the Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.
Comments
No comments here. You can get in touch with me on Mastodon or send me an email if you prefer.