forked from w3c/w3c-api
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHAL-model
218 lines (175 loc) · 9.09 KB
/
HAL-model
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
HAL - Hypertext Application Language
A lean hypermedia type
Author: Mike Kelly <mike@stateless.co>
Created: 2011-06-13
Updated: 2013-09-18 (Updated)
Summary
HAL is a simple format that gives a consistent and easy way to hyperlink between resources in your API.
Adopting HAL will make your API explorable, and its documentation easily discoverable from within the API itself. In short, it will make your API easier to work with and therefore more attractive to client developers.
APIs that adopt HAL can be easily served and consumed using open source libraries available for most major programming languages. It's also simple enough that you can just deal with it as you would any other JSON.
About The Author
Mike Kelly is a software engineer from the UK. He runs an API consultancy helping companies design and build beautiful APIs that developers love.
Quick links
A demo API using HAL called HAL Talk
A list of libraries for working with HAL (Obj-C, Ruby, JS, PHP, C#, etc.)
A list of public hypermedia APIs using HAL
Discussion group (questions, feedback, etc)
General Description
HAL provides a set of conventions for expressing hyperlinks in either JSON or XML.
The rest of a HAL document is just plain old JSON or XML.
Instead of using ad-hoc structures, or spending valuable time designing your own format; you can adopt HAL's conventions and focus on building and documenting the data and transitions that make up your API.
HAL is a little bit like HTML for machines, in that it is generic and designed to drive many different types of application via hyperlinks. The difference is that HTML has features for helping 'human actors' move through a web application to achieve their goals, whereas HAL is intended for helping 'automated actors' move through a web API to achieve their goals.
Having said that, HAL is actually very human-friendly too. Its conventions make the documentation for an API discoverable from the API messages themselves. This makes it possible for developers to jump straight into a HAL-based API and explore its capabilities, without the cognitive overhead of having to map some out-of-band documentation onto their journey.
Examples
The example below is how you might represent a collection of orders with hal+json. Things to look for:
The URI of the main resource being represented ('/orders') expressed with a self link
The 'next' link pointing to the next page of orders
A templated link called 'ea:find' for searching orders by id
The multiple 'ea:admin' link objects contained in an array
Two properties of the orders collection; 'currentlyProcessing' and 'shippedToday'
Embedded order resources with their own links and properties
The compact URI (curie) named 'ea' for expanding the name of the links to their documentation URL
application/hal+json
{
"_links": {
"self": { "href": "/orders" },
"curies": [{ "name": "ea", "href": "http://example.com/docs/rels/{rel}", "templated": true }],
"next": { "href": "/orders?page=2" },
"ea:find": {
"href": "/orders{?id}",
"templated": true
},
"ea:admin": [{
"href": "/admins/2",
"title": "Fred"
}, {
"href": "/admins/5",
"title": "Kate"
}]
},
"currentlyProcessing": 14,
"shippedToday": 20,
"_embedded": {
"ea:order": [{
"_links": {
"self": { "href": "/orders/123" },
"ea:basket": { "href": "/baskets/98712" },
"ea:customer": { "href": "/customers/7809" }
},
"total": 30.00,
"currency": "USD",
"status": "shipped"
}, {
"_links": {
"self": { "href": "/orders/124" },
"ea:basket": { "href": "/baskets/97213" },
"ea:customer": { "href": "/customers/12369" }
},
"total": 20.00,
"currency": "USD",
"status": "processing"
}]
}
}
The HAL Model
The HAL conventions revolve around representing two simple concepts: Resources and Links.
Resources
Resources have:
Links (to URIs)
Embedded Resources (i.e. other resources contained within them)
State (your bog standard JSON or XML data)
Links
Links have:
A target (a URI)
A relation aka. 'rel' (the name of the link)
A few other optional properties to help with deprecation, content negotiation, etc.
Below is an image that roughly illustrates how a HAL representation is structured:
The HAL Information model
How HAL is used in APIs
HAL is designed for building APIs in which clients navigate around the resources by following links.
Links are identified by link relations. Link relations are the lifeblood of a hypermedia API: they are how you tell client developers about what resources are available and how they can be interacted with, and they are how the code they write will select which link to traverse.
Link relations are not just an identifying string in HAL, though. They are actually URLs, which developers can follow in order to read the documentation for a given link. This is what is known as "discoverability". The idea is that a developer can enter into your API, read through documentation for the available links, and then follow-their-nose through the API.
HAL encourages the use of link relations to:
Identify links and embedded resources within the representation
Infer the expected structure and meaning of target resources
Signalling what requests and representations can be submitted to target resources
How to serve HAL
HAL has a media type for both the JSON and XML variants, whos names are application/hal+json and application/hal+xml respectively.
When serving HAL over HTTP, the Content-Type of the response should contain the relevant media type name.
The structure of a HAL document
Minimum valid document
A HAL document must at least contain an empty resource.
An empty JSON object:
{}
Resources
In most cases, resources should have a self URI
Represented via a 'self' link:
{
"_links": {
"self": { "href": "/example_resource" }
}
}
Links
Links must be contained directly within a resource:
Links are represented as JSON object contained within a _links hash that must be a direct property of a resource object:
{
"_links": {
"next": { "href": "/page=2" }
}
}
Link Relations
Links have a relation (aka. 'rel'). This indicates the semantic - the meaning - of a particular link.
Link rels are the main way of distinguishing between a resource's links.
It's basically just a key within the _links hash, associating the link meaning (the 'rel') with the link object that contains data like the actual 'href' value:
{
"_links": {
"next": { "href": "/page=2" }
}
}
API Discoverability
Link rels should be URLs which reveal documentation about the given link, making them "discoverable". URLs are generally quite long and a bit nasty for use as keys. To get around this, HAL provides "CURIEs" which are basically named tokens that you can define in the document and use to express link relation URIs in a friendlier, more compact fashion i.e. ex:widget instead of http://example.com/rels/widget. The details are available in the section on CURIEs a bit further down.
Representing Multiple Links With The Same Relation
A resource may have multiple links that share the same link relation.
For link relations that may have multiple links, we use an array of links.
{
"_links": {
"items": [{
"href": "/first_item"
},{
"href": "/second_item"
}]
}
}
Note: If you're unsure whether the link should be singular, assume it will be multiple. If you pick singular and find you need to change it, you will need to create a new link relation or face breaking existing clients.
CURIEs
"CURIE"s help providing links to resource documentation.
HAL gives you a reserved link relation 'curies' which you can use to hint at the location of resource documentation.
"_links": {
"curies": [
{
"name": "doc",
"href": "http://haltalk.herokuapp.com/docs/{rel}",
"templated": true
}
],
"doc:latest-posts": {
"href": "/posts/latest"
}
}
There can be multiple links in the 'curies' section. They come with a 'name' and a templated 'href' which must contain the {rel} placeholder.
Links in turn can then prefix their 'rel' with a CURIE name. Associating the latest-posts link with the doc documentation CURIE results in a link 'rel' set to doc:latest-posts.
To retrieve documentation about the latest-posts resource, the client will expand the associated CURIE link with the actual link's 'rel'. This would result in a URL http://haltalk.herokuapp.com/docs/latest-posts which is expected to return documentation about this resource.
To be continued...
This relatively informal specification of HAL is incomplete and still in progress. For now, if you would like to have a full understanding please read the formal specification.
RFC
The JSON variant of HAL (application/hal+json) has now been published as an internet draft: draft-kelly-json-hal.
Acknowledgements
Darrel Miller
Mike Amundsen
Mark Derricutt
Herman Radtke
Will Hartung
Steve Klabnik
everyone on hal-discuss
Thanks for the help :)
Notes/todo