Hi,
I'm a relative beginner to the world of API design, and am currently working my way through RESTful concepts, and starting to get my head around HATEOAS.
I mostly understand what is going on, and can envisage how to generate and use links for many scenarios... apart from one, which I can't quite wrap my head around.
Supposing we have a collection of library books, each of which has a current borrower.
The database has a 'book' table, which contains a relationship to the 'borrower' table, which can be easily transformed into a HATEOAS link, such that the data might look something like:
It's easy to see how the client can consume this data and 'look up' borrower '2' as necessary.
However, suppose the client now wants to change the borrower. The client can (relatively easily) look up the new borrower by stripping the id from the link href and get all borrowers, but it's not clear what to put in a POST/PUT back to the server to indicate this change.
A few options I have envisaged are:
1) Post back the HATEOAS data intact, with the href modified to point to the new borrower - the server resolves this back to the borrower_id to update the db relationship.
This feels a bit dirty - the client shouldn't really be sending HATEOAS-style data to the server... should it?
2) Have the server add a 'data' field to the links section that contains the id - something like:
Again the client posts back the HATEOAS data, and the server knows to only consider the 'id' field.
3) Have the links data reference a field in the 'real' data that the client should modify:
{
"book": "APIs are Cool",
"author": "John Smith",
"borrower_id": 2
"links": [
{
"rel": "borrower",
"href": "http://api.example.com/borrowers/2",
"field": "borrower_id"
}
]
}
Here the client can discard the HATEOAS data, and only 'real' fields are POSTed to the server. This feels most 'correct' somehow, but is also a bit of a duplication of data.
2 and 3 feel nicer than 1 - but neither of them really feels 'correct'. I could of course create a completely separate 'relationships' API call, and maintain another table of relationships between borrowers and books, but this seems slightly artificial for one-to-many relationships - and would make 'must have a relationship' constraints difficult to implement, due to the chicken-egg problem of item versus relationship creation order.
I'm probably missing something obvious here, hence this post! If anyone can offer any comments on their preferred approach in this situation I'd be very grateful. No doubt there is a better approach out there I haven't yet seen...
Cheers,
Matthew