In a previous post I have explained how to develop a very simple API server.
Without the associated documentation, the API will be useless. Let’s see how we can use swagger-ui in this project to generate a beautiful documentation.
Note I’m blogging and experimenting, of course, in the “real” life, it’s a lot better to code the API interface before implementing the middleware.
Swagger is a framework. On top of the swagger project is composed of several tools.
The entry point is to write the API interface using the Swagger Formal Specification. I will the use the swagger-ui to display the documentation. The swagger-ui can be modified and recompiled, but I won’t do it (as I don’t want to play with nodejs). Instead I will rely on the “dist” part which can be used “as-is”
Defining the API interface with Swagger
Header and specification version:
Swagger comes with an editor which can be used online.
I will use swagger spec 2.0, as I don’t see any good reason not to do so. Moreover, I will describe the API using the
YAML format instead of the JSON format to be human-friendly.
Indeed, in my
YAML skeleton the header of my specs will then look like this:
The node creation: a POST method
Let’s document the Node creation (as it is the method that we have implemented before).
The node creation is a
POST method, that produces a JSON in output with the request ID of the node created.
The responses code may be:
- 202 : if the request has been taken in account
- 400 : when the request is not formatted correctly
- 500 : if any unhanldled exception occurred
- 502 : if the backend is not accessible (either the RPC server or the backend)
So far, the YAML spec will look like:
So far so good, let’s continue with the input payload. The payload will be formatted in JSON, so I add this directive to the model:
I’ve decided in my previous post that 6 parameters were needed:
- the kind of os
- the size of the machine
- the initial disk size allocated
- the lease (in days)
- the environment
- the description
All the parameters will compose a payload and therefore will be present in the body of the request. The YAML representation of the parameters array is:
Sounds ok, but when I test this implementation in the swagger editor for validation, I get this error:
Swagger Error Data does not match any schemas from 'oneOf'
STFWing and RTFMing…
in the Specifications, I have found this line:
Therefore, I should set a schema object for every parameter in order to define its type. In this example, I don’t want to go too deeply into the swagger specification, so I won’t define any type.
So I have tested the following:
And again, I had a validation error from the editor:
✖ Swagger ErrorOperation cannot have multiple body parameters
Body - The payload that’s appended to the HTTP request. Since there can only be one payload, there can only be one body parameter. The name of the body parameter has no effect on the parameter itself and is used for documentation purposes only. Since Form parameters are also in the payload, body and form parameters cannot exist together for the same operation.
What I must do, is to create a custom type nodeRequest with the input fields as properties and reference it in the body.
Here is the complete structure:
And the proper NodeRequest definition in the definition area:
OK ! The swagger file is valid… Now let’s glue it together with swagger-ui and serve it from the GO API server I have developed before
As written in the README in the github of the project, swagger-ui can be used “as-is” using the files in the dist folder. Let’s get the files from github:
Let’s checkout our project:
and move the
dist folder into the project:
mv /tmp/swagger-ui/dist /tmp/example-iaas
Adding a route to the GO server to serve the static files
I cannot simply add a route in the
routes.go file for this very simple reason:
The loop used in the
router.go is using the
Path method, and to serve the content of the directory, I need to use the
PathPrefix method (see The Gorilla Documentation for more information).
To serve the content, I add this entry to the muxrouter in the
Then I start the server and point my browser to http://localhost:8080/apidocs…
Wait, nothing is displayed…
The final test
As I serve the files from the
./dist directory, what I need to do is to move my
swagger.yaml spec file into the dist subfolder and tell swagger to read it.
As you can see, there is a “Try out” button, which triggers a
curl command… Very helpful to enter a test driven development mode.
On top of that swagger is really helpful and may be a great tool to synthesize the need of a client in term of an interface. Once the API is fully implemented, any client binding may also be generated with the swagger framework.
No not hesitate to clone the source code from github and test the swagger.yaml file in the editor to see how the bindings are generated
You can find all the codes in the github repository here in the branch
The final YAML file can be found here