haveapi 0.22.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/haveapi.gemspec +1 -1
- data/lib/haveapi/client_examples/php_client.rb +6 -9
- data/lib/haveapi/client_examples/ruby_client.rb +1 -1
- data/lib/haveapi/resource.rb +2 -2
- data/lib/haveapi/resources/action_state.rb +2 -5
- data/lib/haveapi/server.rb +18 -0
- data/lib/haveapi/spec/mock_action.rb +2 -2
- data/lib/haveapi/spec/spec_methods.rb +2 -2
- data/lib/haveapi/version.rb +1 -1
- metadata +3 -8
- data/doc/Hooks.md +0 -81
- data/doc/create-client.md +0 -107
- data/doc/json-schema.html +0 -1189
- data/doc/protocol.md +0 -535
- data/doc/protocol.png +0 -0
data/doc/protocol.md
DELETED
@@ -1,535 +0,0 @@
|
|
1
|
-
# Protocol definition
|
2
|
-
HaveAPI defines the format for the self-description and URLs where the self-description
|
3
|
-
can be found.
|
4
|
-
|
5
|
-
# Self-description
|
6
|
-
The API is self-describing. It documents itself. Clients use the self-description
|
7
|
-
to work with the API. The Self-description contains access URLs, HTTP methods,
|
8
|
-
input and output parameters and their validators.
|
9
|
-
A part of description is also an example usage and text notes.
|
10
|
-
|
11
|
-
The API responds to ``OPTIONS /``, which returns description of whole
|
12
|
-
API, containing all its versions. To get description only of selected version,
|
13
|
-
use e.g. ``OPTIONS /v1/``.
|
14
|
-
|
15
|
-
Every action also responds to HTTP method ``OPTIONS``,
|
16
|
-
with which you can get description for selected action. To distinguish actions with
|
17
|
-
the same URL, use parameter ``?method=HTTP_METHOD``.
|
18
|
-
|
19
|
-
Thanks to this ability, API changes immediately reflects in all clients without
|
20
|
-
changing a single line of code. A client can also be used on all APIs with compatible
|
21
|
-
self-describing format, without any changes at all.
|
22
|
-
|
23
|
-
# Protocol versioning
|
24
|
-
Protocol version defines the form and contents of
|
25
|
-
|
26
|
-
- the envelope,
|
27
|
-
- API description,
|
28
|
-
- data transfers.
|
29
|
-
|
30
|
-
Protocol version is in the form `<major>.<minor>`. `major` is incremented
|
31
|
-
whenever a change is made to the protocol that breaks backward compatibility.
|
32
|
-
When backward compatibility is kept and only some new features are added to the
|
33
|
-
protocol, `major` stays and `minor` is incremented.
|
34
|
-
|
35
|
-
# Envelope
|
36
|
-
In addition to output format specified below, every API response
|
37
|
-
is wrapped in an envelope.
|
38
|
-
The envelope reports if action succeeded or failed, provides return value or error
|
39
|
-
messages.
|
40
|
-
|
41
|
-
{
|
42
|
-
"status": true if action succeeded or false if error occured,
|
43
|
-
"response": return value,
|
44
|
-
"message": error message, if status is false,
|
45
|
-
"errors: {
|
46
|
-
"parameter1": ["list", "of", "errors"],
|
47
|
-
"parameter2": ["and", "so", "on"]
|
48
|
-
}
|
49
|
-
}
|
50
|
-
|
51
|
-
Responses for `OPTIONS` requests also send a protocol version in the envelope:
|
52
|
-
|
53
|
-
"version": <version>
|
54
|
-
|
55
|
-
# Description format
|
56
|
-
In this document, the self-description is encoded in JSON. However, it can
|
57
|
-
be encoded in any of the supported output formats.
|
58
|
-
|
59
|
-
## API version
|
60
|
-
|
61
|
-
<a href="/doc/protocol.png">
|
62
|
-
<img src="/doc/protocol.png"
|
63
|
-
alt="Diagram representing the structure of an API version"
|
64
|
-
width="600">
|
65
|
-
</a>
|
66
|
-
|
67
|
-
API version is described as:
|
68
|
-
|
69
|
-
{
|
70
|
-
"authentication": {
|
71
|
-
... authentication methods ...
|
72
|
-
},
|
73
|
-
"resources": {
|
74
|
-
... resources ...
|
75
|
-
},
|
76
|
-
"meta": {
|
77
|
-
"namespace": "_meta"
|
78
|
-
},
|
79
|
-
"help": "/<version>/"
|
80
|
-
}
|
81
|
-
|
82
|
-
See appropriate section for detailed description of each section.
|
83
|
-
|
84
|
-
## Authentication
|
85
|
-
HaveAPI defines an interface for implementing custom authentication methods.
|
86
|
-
HTTP basic and token authentication is built-in.
|
87
|
-
|
88
|
-
Authentication methods can be set per API version. They are a part of
|
89
|
-
the self-description, but must be understood by the client.
|
90
|
-
The client can choose whichever available authentication method he prefers.
|
91
|
-
|
92
|
-
### HTTP basic authentication
|
93
|
-
HTTP basic authentication needs no other configuration, only informs about its presence.
|
94
|
-
|
95
|
-
"basic": {}
|
96
|
-
|
97
|
-
HTTP basic authentication does not support multi-factor authentication.
|
98
|
-
|
99
|
-
### Token authentication
|
100
|
-
Token authentication contains resource ``token``, that is used to acquire
|
101
|
-
and revoke tokens.
|
102
|
-
|
103
|
-
Tokens are acquired by action ``request``, in which the client provides arbitrary
|
104
|
-
login credentials. If the login credentials match, the server either concludes
|
105
|
-
the authentication process, or multiple authentication steps may be necessary.
|
106
|
-
|
107
|
-
For single-step authentication processses, action ``request`` returns the
|
108
|
-
token and its validity period. If multiple authentication steps are necessary,
|
109
|
-
the server signals this by returning ``complete = true``. The client then has
|
110
|
-
to call the next authentication step, which is an action on the ``token``
|
111
|
-
resource, as returned in ``next_action``.
|
112
|
-
|
113
|
-
Tokens are returned in both cases. If the authentication is finished, the token
|
114
|
-
is then used for authenticating further requests. If the authentication continues,
|
115
|
-
the token is used to authenticate the next authentication request, which then
|
116
|
-
returns another token.
|
117
|
-
|
118
|
-
After the authentication is complete, acquired tokens can be renewed using action
|
119
|
-
``renew`` and revoked by calling the ``revoke`` action.
|
120
|
-
|
121
|
-
"token": {
|
122
|
-
"http_header": "<name of HTTP header to transfer token in, by default X-HaveAPI-Auth-Token>",
|
123
|
-
"query_parameter": "<name of query parameter for token, by default auth_token>",
|
124
|
-
"resources": {
|
125
|
-
"actions": {
|
126
|
-
"request": {
|
127
|
-
...
|
128
|
-
"input": {
|
129
|
-
...
|
130
|
-
"parameters": {
|
131
|
-
"user": ...
|
132
|
-
"password": ...
|
133
|
-
"lifetime": ...
|
134
|
-
"interval": ...
|
135
|
-
},
|
136
|
-
...
|
137
|
-
},
|
138
|
-
"output": {
|
139
|
-
...
|
140
|
-
"parameters": {
|
141
|
-
"token": ...
|
142
|
-
"valid_to": ...
|
143
|
-
"complete": true/false
|
144
|
-
"next_action": ...
|
145
|
-
},
|
146
|
-
...
|
147
|
-
},
|
148
|
-
...
|
149
|
-
}
|
150
|
-
"revoke": ...
|
151
|
-
}
|
152
|
-
}
|
153
|
-
}
|
154
|
-
|
155
|
-
The format for ``resources`` section is the same as for any other resource.
|
156
|
-
|
157
|
-
## Resources
|
158
|
-
Each resource is described as:
|
159
|
-
|
160
|
-
"<resource_name>": {
|
161
|
-
"description": "Some description that explains everything",
|
162
|
-
"actions": {
|
163
|
-
... actions ...
|
164
|
-
},
|
165
|
-
"resources": {
|
166
|
-
... nested resources ...
|
167
|
-
}
|
168
|
-
}
|
169
|
-
|
170
|
-
## Actions
|
171
|
-
Every action is described as:
|
172
|
-
|
173
|
-
"<action_name>": {
|
174
|
-
"auth": true|false,
|
175
|
-
"description": "Describe what this action does",
|
176
|
-
"aliases": ["list", "of", "aliases"],
|
177
|
-
"blocking": true|false,
|
178
|
-
"input": {
|
179
|
-
"layout": "layout type",
|
180
|
-
"namespace": "namespace name",
|
181
|
-
"parameters": {
|
182
|
-
... parameters ...
|
183
|
-
}
|
184
|
-
},
|
185
|
-
"output": {
|
186
|
-
"layout": "layout type",
|
187
|
-
"namespace": "namespace name",
|
188
|
-
"parameters": {
|
189
|
-
... parameters ...
|
190
|
-
}
|
191
|
-
},
|
192
|
-
"examples": [
|
193
|
-
... list of examples ...
|
194
|
-
],
|
195
|
-
"meta": ... metadata ...,
|
196
|
-
"path": "URL for this action",
|
197
|
-
"method": "HTTP method to be used",
|
198
|
-
"help": "URL to get this very description of the action"
|
199
|
-
}
|
200
|
-
|
201
|
-
### Layouts
|
202
|
-
Layout type is specified for input/output parameters. Thanks to the layout type,
|
203
|
-
clients know how to send the request and how to interpret the response.
|
204
|
-
|
205
|
-
Defined layout types:
|
206
|
-
|
207
|
-
- object - mainly the response is to be treated as an instance of a resource
|
208
|
-
- object_list - list of objects
|
209
|
-
- hash - simply a hash of parameters, it is to be treated as such
|
210
|
-
- hash_list - list of hashes
|
211
|
-
|
212
|
-
In client libraries, the ``object`` layout output usually results in returning
|
213
|
-
an object that represents the instance of the resource. The parameters are defined
|
214
|
-
as object properties and the like.
|
215
|
-
|
216
|
-
### Namespace
|
217
|
-
All input/output parameters are put in a namespace, which is usually
|
218
|
-
the name of the resource.
|
219
|
-
|
220
|
-
For example:
|
221
|
-
|
222
|
-
{
|
223
|
-
"user": {
|
224
|
-
... parameters ...
|
225
|
-
}
|
226
|
-
}
|
227
|
-
|
228
|
-
## Parameters
|
229
|
-
There are two parameter types.
|
230
|
-
|
231
|
-
### Data types
|
232
|
-
The type can be one of:
|
233
|
-
|
234
|
-
- String
|
235
|
-
- Text
|
236
|
-
- Boolean
|
237
|
-
- Integer
|
238
|
-
- Float
|
239
|
-
- Datetime
|
240
|
-
|
241
|
-
"<parameter_name>": {
|
242
|
-
"required": true/false/null,
|
243
|
-
"label": "Label for this parameter",
|
244
|
-
"description": "Describe it's meaning",
|
245
|
-
"type": "<one of the data types>",
|
246
|
-
"validators": ... validators ...,
|
247
|
-
"default": "default value that is used if the parameter is omitted",
|
248
|
-
"protected": true/false
|
249
|
-
}
|
250
|
-
|
251
|
-
|
252
|
-
#### Validators
|
253
|
-
Every parameter has its own validators. Any of the following validators
|
254
|
-
may be present. Input value must pass through all validators in order
|
255
|
-
to be considered valid.
|
256
|
-
|
257
|
-
##### Acceptance
|
258
|
-
Used when a parameter must have one specific value.
|
259
|
-
|
260
|
-
"accept": {
|
261
|
-
"value": <value to accept>,
|
262
|
-
"message": "has to be <value>"
|
263
|
-
}
|
264
|
-
|
265
|
-
##### Presence
|
266
|
-
The parameter must be present. If `empty` is `false`, leading and trailing
|
267
|
-
whitespace is stripped before the check.
|
268
|
-
|
269
|
-
"present": {
|
270
|
-
empty: true/false,
|
271
|
-
message: "must be present"
|
272
|
-
}
|
273
|
-
|
274
|
-
##### Confirmation
|
275
|
-
Used to confirm that two parameters have either the same value or not have the
|
276
|
-
same value. The former can be used e.g. to verify that passwords are same
|
277
|
-
and the latter to give two different e-mail addresses.
|
278
|
-
|
279
|
-
"confirm": {
|
280
|
-
"equal": true/false,
|
281
|
-
"parameter": <parameter_name>,
|
282
|
-
"message": "must (or must not) be the same as <parameter_name>"
|
283
|
-
}
|
284
|
-
|
285
|
-
##### Inclusion
|
286
|
-
The parameter can contain only one of given options.
|
287
|
-
|
288
|
-
"include": {
|
289
|
-
"values": ["list", "of", "allowed", "values"],
|
290
|
-
"message": "%{value} cannot be used"
|
291
|
-
}
|
292
|
-
|
293
|
-
If the `values` are a list, than it is a list of accepted values.
|
294
|
-
If the `values` are a hash, the keys of that hash are accepted values,
|
295
|
-
values in that hash are to be shown in UI.
|
296
|
-
|
297
|
-
"include": {
|
298
|
-
"values": {
|
299
|
-
"one": "Fancy one",
|
300
|
-
"two": "Fancy two"
|
301
|
-
},
|
302
|
-
"message": "%{value} cannot be used"
|
303
|
-
}
|
304
|
-
|
305
|
-
##### Exclusion
|
306
|
-
The parameter can be set to anything except values listed here.
|
307
|
-
|
308
|
-
"exclude": {
|
309
|
-
"values": ["list", "of", "excluded", "values"],
|
310
|
-
"message": "%{value} cannot be used"
|
311
|
-
}
|
312
|
-
|
313
|
-
##### Specific format
|
314
|
-
If `match` is true, the parameter must pass given regular expression.
|
315
|
-
Otherwise it must not pass the regular expression.
|
316
|
-
|
317
|
-
"format": {
|
318
|
-
"rx": "regular expression",
|
319
|
-
"match": true/false,
|
320
|
-
"description": "human-readable description of the regular expression",
|
321
|
-
"message": "%{value} is not in a valid format"
|
322
|
-
}
|
323
|
-
|
324
|
-
##### Length
|
325
|
-
Useful only for `String` and `Text` parameters. Checks the length of given string.
|
326
|
-
It may check either
|
327
|
-
|
328
|
-
- minimum
|
329
|
-
- maximum
|
330
|
-
- minimum and maximum
|
331
|
-
- constant length
|
332
|
-
|
333
|
-
The length validator must therefore contain one or more checks, but cannot
|
334
|
-
contain both min/max and equality.
|
335
|
-
|
336
|
-
Length range:
|
337
|
-
|
338
|
-
"length": {
|
339
|
-
"min": 0,
|
340
|
-
"max": 99,
|
341
|
-
"message": "length has to be in range <0,99>"
|
342
|
-
}
|
343
|
-
|
344
|
-
Constant length:
|
345
|
-
|
346
|
-
"length": {
|
347
|
-
"equals": 10,
|
348
|
-
"message": "length has to be 10"
|
349
|
-
}
|
350
|
-
|
351
|
-
##### Numericality
|
352
|
-
Numericality implies that the parameter must be a number, i.e. `Integer`, `Float`
|
353
|
-
or `String` containing only digits. It can check that the number is in a specified
|
354
|
-
range and can provide a step. The validator can contain one or more of these conditions.
|
355
|
-
|
356
|
-
"number": {
|
357
|
-
"min": 0,
|
358
|
-
"max": 99,
|
359
|
-
"step": 3,
|
360
|
-
"mod": 3,
|
361
|
-
"even": true/false,
|
362
|
-
"odd": true/false
|
363
|
-
}
|
364
|
-
|
365
|
-
##### Custom validation
|
366
|
-
Custom validation cannot be documented by the API. The developer may or may not
|
367
|
-
provide information that some non-documented validation takes place. The documentation
|
368
|
-
contains only the description of the validations that may be shown to the user,
|
369
|
-
but is not evaluated client-side, only server-side.
|
370
|
-
|
371
|
-
"custom": "description of custom validation"
|
372
|
-
|
373
|
-
### Resource association
|
374
|
-
This is used for associations between resources, e.g. car has a wheel.
|
375
|
-
|
376
|
-
"<parameter_name>": {
|
377
|
-
"required": true/false/null,
|
378
|
-
"label": "Label for this parameter",
|
379
|
-
"description": "Describe it's meaning",
|
380
|
-
"type": "Resource",
|
381
|
-
"resource": ["path", "to", "resource"],
|
382
|
-
"value_id": "<name of a parameter that is used as an id>",
|
383
|
-
"value_label": "<name of a parameter that is used as a value>",
|
384
|
-
"value": {
|
385
|
-
"path": "URL to 'show' action of associated resource",
|
386
|
-
"method": "HTTP method to use",
|
387
|
-
"help": "URL to get the associated resource's 'show' description"
|
388
|
-
},
|
389
|
-
"choices": {
|
390
|
-
"path": "URL to action that returns a list of possible associations",
|
391
|
-
"method": "HTTP method to use",
|
392
|
-
"help": "URL to description of the list action"
|
393
|
-
}
|
394
|
-
}
|
395
|
-
|
396
|
-
The _resource_ type also has a different output in action response. It returns
|
397
|
-
a hash containing associated resource ID and its label, so that clients
|
398
|
-
can show the human-friendly label instead of just an ID.
|
399
|
-
|
400
|
-
"<parameter_name>": {
|
401
|
-
"<value of value_id from description>": <resource id>,
|
402
|
-
"<value of value_label from description>": "<label>"
|
403
|
-
}
|
404
|
-
|
405
|
-
## Examples
|
406
|
-
Examples are described in a generic way, so that every client can
|
407
|
-
render them according to its syntax.
|
408
|
-
|
409
|
-
{
|
410
|
-
"title": "A title",
|
411
|
-
"path_params: [ ... array of integers ... ],
|
412
|
-
"request": {
|
413
|
-
... a hash of request parameters ...
|
414
|
-
},
|
415
|
-
"response": {
|
416
|
-
... a hash of response parameters ...
|
417
|
-
},
|
418
|
-
"status": true/false,
|
419
|
-
"message": "Message explaining an error if it occurs",
|
420
|
-
"errors": {
|
421
|
-
"<parameter>": [ ... array of errors ... ],
|
422
|
-
},
|
423
|
-
http_status: 200,
|
424
|
-
"comment": "Description of the example"
|
425
|
-
}
|
426
|
-
|
427
|
-
## Metadata
|
428
|
-
Metadata can be global and per-object. Global metadata are sent once for each
|
429
|
-
response, where as per-object are sent with each object that is a part of the
|
430
|
-
response.
|
431
|
-
|
432
|
-
{
|
433
|
-
"global": {
|
434
|
-
"input": ... parameters or null ...,
|
435
|
-
"output: ... parameters or null ...
|
436
|
-
} or null,
|
437
|
-
|
438
|
-
"object": {
|
439
|
-
"input": ... parameters or null ...,
|
440
|
-
"output: ... parameters or null ...
|
441
|
-
} or null,
|
442
|
-
}
|
443
|
-
|
444
|
-
## Blocking mode
|
445
|
-
Blocking mode is for actions whose execution takes a long time. Clients can monitor
|
446
|
-
progress of such actions and even cancel their execution.
|
447
|
-
|
448
|
-
The blocking action returns its result as usual, but provides a unique identifier using
|
449
|
-
which clients can check its status via the `ActionState` resource. The state identifier
|
450
|
-
is passed through global output metadata in a parameter called `action_state_id`.
|
451
|
-
Resource `ActionState` is a part of the API's documentation and is the standard interface
|
452
|
-
for browsing and manipulating currently active blocking actions.
|
453
|
-
|
454
|
-
An action is blocking if parameter `blocking` in its description is `true` and if
|
455
|
-
`action_state_id` is present in its metadata after each call. This allows actions
|
456
|
-
to be blocking only when needed.
|
457
|
-
|
458
|
-
## List API versions
|
459
|
-
Send request ``OPTIONS /?describe=versions``. The description format:
|
460
|
-
|
461
|
-
{
|
462
|
-
"versions": [1, 2, 3, ... list of versions],
|
463
|
-
"default": <which version is default>
|
464
|
-
}
|
465
|
-
|
466
|
-
## Describe default version
|
467
|
-
Send request ``OPTIONS /?describe=default`` the get the description
|
468
|
-
of the default version.
|
469
|
-
|
470
|
-
## Describe the whole API
|
471
|
-
It is possible to get self-description of all versions at once.
|
472
|
-
|
473
|
-
Send request ``OPTIONS /``. The description format:
|
474
|
-
|
475
|
-
{
|
476
|
-
"default_version": <which version is default>,
|
477
|
-
"versions": {
|
478
|
-
"default": ... full version self-description ...,
|
479
|
-
"<version>": ... full version self-description,
|
480
|
-
... all other versions ...
|
481
|
-
}
|
482
|
-
}
|
483
|
-
|
484
|
-
# Authorization
|
485
|
-
Actions may require different levels of authorization. HaveAPI provides means for
|
486
|
-
implementing authorization, but it is not self-described.
|
487
|
-
|
488
|
-
If the user is authenticated when requesting self-description, only allowed
|
489
|
-
resources/actions/parameters will be returned.
|
490
|
-
|
491
|
-
# Input/output formats
|
492
|
-
For now, the only supported input format is JSON.
|
493
|
-
|
494
|
-
Output format can be chosen by a client. However, no other format than JSON is built-in.
|
495
|
-
The output format can be chosen with HTTP header ``Accept``.
|
496
|
-
|
497
|
-
# Request
|
498
|
-
Action URL and HTTP method the client learns from the self-description.
|
499
|
-
|
500
|
-
Example request:
|
501
|
-
|
502
|
-
POST /users HTTP/1.1
|
503
|
-
Content-Type: application/json
|
504
|
-
Accept: application/json
|
505
|
-
Connection: Close
|
506
|
-
|
507
|
-
{
|
508
|
-
"user": {
|
509
|
-
"login": "mylogin",
|
510
|
-
"name": "Very Name",
|
511
|
-
"role": "admin"
|
512
|
-
}
|
513
|
-
}
|
514
|
-
|
515
|
-
# Response
|
516
|
-
Clients know how to interpret the response thanks to the layout type they learn
|
517
|
-
from the self-description.
|
518
|
-
|
519
|
-
Example response to the request above:
|
520
|
-
|
521
|
-
Content-Type: application/json
|
522
|
-
|
523
|
-
{
|
524
|
-
"status": true,
|
525
|
-
"response": {
|
526
|
-
"user": {
|
527
|
-
"id": 1,
|
528
|
-
"login": "mylogin",
|
529
|
-
"name": "Very Name",
|
530
|
-
"role": "admin"
|
531
|
-
}
|
532
|
-
},
|
533
|
-
"message": null,
|
534
|
-
"errors: null
|
535
|
-
}
|
data/doc/protocol.png
DELETED
Binary file
|