0
votes

Designing API using JSONAPI 1.0 standard there is no PUT method. There is only POST method for create resource and PATCH for partially update. We have use case where user can send request to the server and if resource doesn't exist then must be created otherwise updated. RFC describe such method as a PUT. Next quoting mentioned RFC 5789 standard for PATCH there is information:

"If the Request-URI does not point to an existing resource, the server MAY create a new resource, depending on the patch document type (whether it can logically modify a null resource) and permissions, etc."

Is it good idea to have PATCH method for update and create resource? Which standard should be used to support both PUT and PATCH methods (maybe OpenApi)?

How to interpret RFC description?

Best Regards

2

2 Answers

1
votes

According to Postel's law one should be conservative in what you do, be liberal in what you accept from others.

Two common media-types used with PATCH are application/json-patch+json (a.k.a. JSON Patch) and application/json-merge-patch+json (a.k.a MergePatch).

MergePatch defines a couple of rules that determine whether a part needs to be added, removed or updated. The spec defines that a request received of that type needs to be processed by calling a function that takes in two arguments, the target resource and the representation received. The target itself might be either a JSON value or undefined. If the resource does not yet exist it is undefined and will lead to all of the values in the received patch document to be added to the yet undefined resource. This is basically your resource creation then.

JSON Patch, in contrast to MergePatch, is specified to only operate on JSON documents. There is no mention how the patch needs to be applied in case no resource was yet available. This makes somehow sense if you look at the operations is offers, such as test, remove, replace or move that only work if there is a counterpart in the original JSON document availalbe. This media-type is quite close to the actual PATCH definition in that a client sends a set of instructions, which were previously calculate by the client, that need to be applied atomically by the server. Either all or none of the changes are applied. Here a client should have already fetched the current state of the target resource beforehand, otherwise it wont be able to calculate the necessary changes to transform the current representation into the desired one. So applying a representation of that media-type only makes sense if there is already a resource available. If the client saw that no target resource is yet available it simply can use POST then to create the resource. If a client though sends a patch document containing only add operations I'd create a JSON representation and add all of the fields accordingly though.

As you see there are two different takes on how PATCHing can be done in HTTP. One being very close to the original idea of how patching is done in software engineering for decades while the other method being a more pragmatic approch to partial updating remote resources. Which one you use or support (in best case both) is your choice.

1
votes

We have use case where user can send request to the server and if resource doesn't exist then must be created otherwise updated.

The right answer, in this case, is almost certainly going to be to POST your request to the collection resource, and let the server figure out the "right" thing to do.

A resource can be created by sending a POST request to a URL that represents a collection of resources.

Using PUT to create a resource assumes that the client can/should guess what the correct identifier for the new resource should be. If we're not giving the client that authority/control, then the request needs to instead use a stable target-uri, and the server computes the side effects on other resources.

In JSON:API, the server gets to control the choice of URI for the new item.

POST /photos HTTP/1.1
Content-Type: application/vnd.api+json

...

HTTP/1.1 201 Created
Location: http://example.com/photos/550e8400-e29b-41d4-a716-446655440000

If the API were supporting PUT semantics, an equivalent change would look something like

PUT /photos/550e8400-e29b-41d4-a716-446655440000 HTTP/1.1
Content-Type: application/vnd.api+json

HTTP/1.1 201 Created

But JSON:API has decide that PUT isn't interesting yet. Reading between the lines, the authors decided that PUT should be reserved until more implementations demonstrate that they understand the HTTP spec.

So instead you have POST to the collection for the create, and PATCH on the item to for partial or complete replacement.

That in turn implies that if the client doesn't/cannot know that a resource already exists, that it should POST to the collection. The server, in turn, should be aware that the resource may already exist, and do something sensible (replace the representation of the resource, redirect the client to the resource, etc). How the server achieves that would be an implementation detail.

Looking into Internet deal with REST HTTP methods I have never seen that PATCH can be used for resource creation therefore I am surprised that JsonApi forgo PUT method.

PATCH can certainly be used for resource creation -- see RFC 5789

If the Request-URI does not point to an existing resource, the server MAY create a new resource, depending on the patch document type (whether it can logically modify a null resource) and permissions, etc.

It's an uncommon choice, because PUT semantics are a better fit for that use case. Choosing to support PATCH, but not PUT, is weird.

I am surprised that JsonApi forgo PUT method

I am also surprised.

It might be possible to resolve your concerns by registering a new profile, encouraging the community to adopt a common pattern for the semantics that you need.