Question3r
Question3r

Reputation: 3782

using a POST route when linking a resource to another one

So let's say you have two entities Product and Category. One product can have multiple categories and one category can have multiple products.

When it comes to the API design you want to create endpoints to add / remove categories from a product. The first approach would be this

which is fine but I normally use POST to create a new resource and send back a 201. Another approach would be

and send a bool if you want to add / remove it. The second approach seems to fit better (just return a 200) but the body payload looks a bit ugly.

{
    "add": true
}

Or call the patch route without a body payload and just toggle it? If that product is linked to the category remove it, otherwise add it.

What is the best practise for adding / removing a resource from another one?

Upvotes: 0

Views: 326

Answers (1)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57257

I suggest that you review Jim Webber's 2011 talk.

If we are doing REST, then we are achieving our goals using general purpose message semantics. When HTTP is our application of choice, then our general purpose message semantics are those associated with transferring documents over a network.

You deliver information to a system by proposing changes to a resource.

One common form of change is a modification of a representation of the resource. In your case, that would suggest a resource that is a list of all categories associated with the product. So you would GET the current representation of that resource, make local changes to your copy, then PUT your updated representation back to the same resource.

GET /products/1/categories
200 OK
Content-Type: text/plain

A
B
C
D
PUT /products/1/categories
Content-Type: text/plain

A
B
E
F
G
200 OK

When the representation of the resource is very large (relative to the size of the HTTP headers), and the edits you want to support are often going to be small, then it can make sense to support PATCH, accepting one of the standardized patch document formats.

The other approach is to POST to the resource a document that describes some change to be made. See It is okay to use POST, by Roy Fielding:

POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.”

This is how most of the pre-javascript HTML web worked; HTML forms would tell clients how to create an application/x-www-form-urlencoded document that the target resource would know how to interpret.

POST /products/1/categories
Content-Type: application/x-www-form-urlencoded

remove=C,D&add=E,F,G

and that worked great; the web was catastrophically successful.

Forms work because the text/html media type has a standardized definition of forms, and how to process them. You can do something similar with your own media types; defining within the representations how to find interesting links that advertise the capabilities of some resource.

Another approach is to use [web links]; you define the semantics of a link relation

the relation http://example.org/abc indicates that the target resource is capable of understanding and handling POST requests containing application/prs.xyz+json documents)

And then you embed those link relations either into your representations, into the HTTP headers, or both. Then any client that understands the semantics of the link relation and the associated media types will be able to take advantage of the advertised capability.

See RFC 5023 to see how this approach was applied in Atom.

Upvotes: 1

Related Questions