Search code examples
reststandardsrelationhateoas

REST: Relations between individual resources


Can someone tell me how to "RESTfully" create a relation between two individual resources?
I have figured out several approaches, but I would like to stick to standards.
I'll list several examples to show you guys what I already came up with.
Examples will have a post resource which has to be linked to a category resource.

Note: all examples presume that both resources already exist.

Ex 1:

PATCH /post/1 HTTP/1.1
Host: api-host
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache

{
    "post": {
        "links": {
            "category": "2"
        }
    }
}

Ex 2:

POST /post/1/category/2 HTTP/1.1
Host: api-host
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache

{}

Ex 3:

POST /relations?post=id&category=id
Host: api-host
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache

{}

And what would be the best way to remove the relationship between these 2 resources?

"Solution":
As LINK and UNLINK aren't supported anymore, the best solution imo (hat tip @Bramus) would be the PATCH example.

So to create a link you would call:

PATCH /post/1 HTTP/1.1
Host: api-host
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache

{
    "post": {
        "links": {
            "category": "2"
        }
    }
}

And to remove it:

PATCH /post/1 HTTP/1.1
Host: api-host
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache

{
    "post": {
        "links": {
            "category": ""
        }
    }
}

Solution

  • To place a Post into a Category I'd use a simple PATCH passing in all those categories as an array (if multiple categories may be selected), or a single category key-value pair.

    • Multiple Categories:

      PATCH /post/1 HTTP/1.1
      Host: api-host
      Accept: application/json
      Content-Type: application/json
      Cache-Control: no-cache
      
      {
          "categories": [2, 3]
      }
      
    • Single Category:

      PATCH /post/1 HTTP/1.1
      Host: api-host
      Accept: application/json
      Content-Type: application/json
      Cache-Control: no-cache
      
      {
          "category": 2
      }
      

    It resembles your first example, yet it differs a little as it passes in the categories as an array / single value. I prefer this method as it mimics what one would do via a normal HTML form: multiple checkboxes for multiple categories (result is an array that gets posted) or a dropdown (result is a single value that gets posted).

    On a sidenote I don't see a category as a link, but as a sub-entity/sub-resource:

    • Sub-entities indicate a relationship between two (mostly different type of) entities.
    • Links are mostly used for navigation (next, prev, parent, me, ...)

    The use of the links key inside your PATCH is not compatible with this ideology.