Writing, Mocking and Testing API document with API Blueprint, aglio, drakov and dredd

Sick of writing and reading API documents in shity Google Drive? You should learn how to write API documents with API Blueprint!

Writing Documentation


Before We Start

This blog post only include basic syntax to write .apib files that can be test and start a mock server with. Learn more advance syntax at API Blueprint

All the source mention below can be found here: https://github.com/darkcl/api-blueprint-stack

Folder structure

Setup the api folder structure like this:

1
2
3
4
5
6
7
./
├── docs
│   ├── request # Request Body JSON
│   ├── response # Response Body JSON
│   ├── schema # Schema JSON
│   └── blog.apib # API Blue Print Document
└── server # Server Code

I use VSCode as my editor to create and edit apib file. VSCode has an awesome plugins (API Elements) that will help you format and jump to different endpoint easily.

API Blueprint Syntax with include

Let’s create an api that list all post on a simple blog.

Create docs/blog.apib with following content

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
FORMAT: 1A

# Blog

Blog is a simple API to manage a blog

# Group Post

## Post Collection [/post]

### List All Post [GET]

+ Response 200 (application/json; charset=utf-8)

+ Body

<!-- include(response/post/get-200-list.json) -->

+ Schema

<!-- include(schema/posts.json) -->

The <!-- include( ... ) --> syntax can be used when you want to include content in a different file.

Reading the documents in browser

In this section, you will need aglio

1
npm i -g aglio

After install aglio, you can start a local server that serve your api document

1
aglio -i ./docs/blog.apib -t slate -s

You can export a static html too

1
aglio -i ./docs/blog.apib -t slate -o ./docs/index.html

Start a mock server with your .apib file


Compile apib without include tags

After you finish the documentation, you can start mocking server with drakov

But drakov cannot read include tags, so you need to run the following command

1
aglio -i ./docs/blog.apib --compile -o out.apib

Start Server

In this section, you need drakov

1
npm i -g drakov

Create a config.js

1
2
3
4
5
6
7
module.exports = {
sourceFiles: 'out.apib',
debugMode: false,
discover: true,
watch: true,
ignoreHeader: ['Accept', 'Content-Type']
};

Run the server

1
drakov --config ./config.js

You can try it out with curl

1
2
3
4
5
6
7
8
9
10
11
> curl http://localhost:3000/post
[
{
"id": 1,
"content": "Post #1"
},
{
"id": 2,
"content": "Post #2"
}
]

Multiple Response

In your documentation, you can define multiple responses

Add these line in your docs/blog.apib

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
### Create Post [POST]

+ Request

+ Body

<!-- include(request/post/post-create.json) -->

+ Response 200 (application/json; charset=utf-8)

+ Body

<!-- include(response/post/post-200-single.json) -->

+ Schema

<!-- include(schema/post.json) -->

+ Request

Duplicated post id

+ Body

<!-- include(request/post/post-create-duplicate.json) -->

+ Response 400

Define the request sample json in request/post/post-create.json

1
2
3
4
{
"id": 3,
"content": "Post #3"
}

Define fail case request sample json in request/post/post-create-duplicate.json

1
2
3
4
{
"id": 2,
"content": "Post #2"
}

Create sample response in response/post/post-200-single.json

1
2
3
4
{
"id": 3,
"content": "Post #3"
}

Compile the file and start server again

1
2
aglio -i ./docs/blog.apib --compile -o out.apib
drakov --config ./config.js

You can try out with curl

1
2
3
4
5
6
7
8
curl -X POST \
http://localhost:3000/post \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-d '{
"content": "Post #2",
"id": 2
}'

It should response with response code 400 and empty response body

Test your document with dredd


Starting a testing server with docker

In the real situation, you will start using dredd to test api endpoint when you finish / implementing your server

For this blog post, we can keep using the drakov server to try out dredd functions

Install and configure dredd

In your api document root folder, run the following command

1
npm i -g `dredd`

Create dredd.yml

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
dry-run: null
hookfiles: null
language: nodejs
sandbox: false
server: null
server-wait: 3
init: false
custom: {}
names: false
only: []
reporter: []
output: []
header: []
sorted: false
user: null
inline-errors: false
details: false
method: []
color: true
level: info
timestamp: false
silent: false
path: []
hooks-worker-timeout: 5000
hooks-worker-connect-timeout: 1500
hooks-worker-connect-retry: 500
hooks-worker-after-connect-wait: 100
hooks-worker-term-timeout: 5000
hooks-worker-term-retry: 500
hooks-worker-handler-host: 127.0.0.1
hooks-worker-handler-port: 61321
config: ./dredd.yml
blueprint: out.apib
endpoint: 'http://localhost:3000'

Then start the test!

1
2
3
4
5
6
7
8
> dredd
info: Configuration './dredd.yml' found, ignoring other arguments.
info: Beginning Dredd testing...
pass: GET (200) /post duration: 32ms
pass: POST (200) /post duration: 10ms
pass: POST (400) /post duration: 6ms
complete: 3 passing, 0 failing, 0 errors, 0 skipped, 3 total
complete: Tests took 51ms

References & Source Location


You can clone the complete project here: https://github.com/darkcl/api-blueprint-stack

Share Comments