mikekelly / hal_specification

HAL Specification
http://stateless.co/hal_specification.html
618 stars 58 forks source link

How to link two documents... #5

Open j opened 11 years ago

j commented 11 years ago

So the spec shows how links look in a response. What is the suggested way of linking two documents?

Is it still going forward with Link headers and a LINK HTTP method?

LINK: /user/1
Link: </user/2>; rel="best_friend", </user/3>; rel="boss"

and

UNLINK: /user/1
Link: </user/2>; rel="best_friend"

Or to just have a LINK HTTP method intake a LINK object as it is represented?:

LINK: /user/1
{
    "best_friend" : { "href": "/user/2" },
    "boss"        : { "href": "/user/3" }
}

and

UNLINK: /user/1
{ "best_friend" : { "href": "/user/2" } }

I would personally love to see #2 because it's simple and straightforward and matches it's represented state and clients don't need to worry about setting a header before the request and what not (KISS).

Of course on the application level, it would need to know how to resolve links if they want to have a literal (non-RESTful) connection between the two (MySQL FKs, MongoDB DBRefs, etc, etc)

There not very many resources on the net referencing the LINK action and how to go about doing it, however, there's a lot of talk about representing them in a response... Thus bringing confusion.

Anyway, which is right or proper?

mikekelly commented 11 years ago

To link two resources together, you can POST/PUT hal+json to a given resource.

Hal specifies the processing rules for the representation, that's all - it is down to your application to establish how it's transitions actually work

Cheers, M

On 16 Jan 2013, at 02:52, Jordan Stout notifications@github.com wrote:

So the spec shows how links look in a response. What is the suggested way of linking two documents?

Is it still going forward with Link headers and a LINK HTTP method?

LINK: /user/1 Link: </user/2>; rel="best_friend", </user/3>; rel="boss" and

UNLINK: /user/1 Link: </user/2>; rel="best_friend" Or to just have a LINK HTTP method intake a LINK object as it is represented?:

LINK: /user/1 { "best_friend" : { "href": "/user/2" }, "boss" : { "href": "/user/3" } } and

UNLINK: /user/1 { "best_friend" : { "href": "/user/2" } } I would personally love to see #2 because it's simple and straightforward and matches it's represented state and clients don't need to worry about setting a header before the request and what not (KISS).

Of course on the application level, it would need to know how to resolve links if they want to have a literal (non-RESTful) connection between the two (MySQL FKs, MongoDB DBRefs, etc, etc)

There not very many resources on the net referencing the LINK action and how to go about doing it, however, there's a lot of talk about representing them in a response... Thus bringing confusion.

Anyway, which is right or proper?

— Reply to this email directly or view it on GitHub.

j commented 11 years ago

Hmm, Yeah I get that. RFC2068 suggests link headers (http://tools.ietf.org/html/rfc2068#section-19.6.2.4). I find it weird that specs try to create a representational standard without explaining how to create the representation.

I feel that if the HAL spec defined how to link two resources together, people working with Backbone, Knockout, HAL clients, etc, etc, could all be in sync with how to create a link.

Also, your suggested way is to POST/PUT to the resource; however, PUT replaces the resource, so you have to pass in the links every time.. which (IMO) on an application side can be heavy since applications have to parse the link href and get the ID and identify the resource (this is probably 90% of what people will be doing), and this is going to be on every PUT request. Another problem I see is that your HAL Backbone.js library doesn't follow that idea since it unset's the link attributes. However, PATCH it wouldn't be a big deal, but not many people support patch I've seen.

I do like the spec and how it looks on paper.

I just feel that it would be great if there was a standard in place of how to create the non-automatic (next, self, etc) links.

mikekelly commented 11 years ago

For me, what you are describing is outside of what the media type specification should include. HAL is meant to be simple, which it will not be if it starts to include semantics about resource creation protocols (ala AtomPub).

If this is something that you think is important and should be standardised, there is a way for you to do this: establish a set of link relations that define the creation protocol you are looking for, and share them with the world.

What do you think?

francescobragagna commented 8 years ago

looking at some "public hypermedia APIs using HAL" it's not clear to me the same problem.

to add to user/1 a new friend in it's friend list I like to post as suggested above an user to user/1/friends.

When I ask for user 1 friends I will receive something like: (GET user/1/friends)

_embedded: {
      friends: [
            {name: 'jack',  _links: {'self': {href: user/12}}},
            {name: 'john',  _links: {'self': {href: user/18}}},
            {name: 'maggie',  _links: {'self': {href: user/21}}}
     ]
}

How to remove one specific friend? if we say that every embedded element has a standard attribute called 'rel' (describing relationship between object embedded, and object 'father') in this example in it's links like these:

     friends: [
            {name: 'jack',  _links: {'self': {href: user/12}, 'rel': {href: user/1/friends/12}}},
            {name: 'john',  _links: {'self': {href: user/18}, 'rel': {href: user/1/friends/18}}},
            {name: 'maggie',  _links: {'self': {href: user/21}, 'rel': {href: user/1/friends/12}}}
     ]

to remove this relationship i simply need to call a DELETE of user/1/friends/18. user/18 still exists, and it could be friend of many others.