As you know, Apicultur is built with API Manager, the Open Source solution by WSO2 for managing and publishing APIs. This middleware solution offers a complete web application that allows developers to find, discover and subscribe to APIs, and allows publishers to make APIs publicly available adding security and service management.
Adding documentation that is easy to understand and read it’s an important step to API publishing. We decided to add Swagger documentation to the API Manager in Apicultur, as Swagger documentation allows to test the API and gives clear insight into how the API responds to parameters and options without needing to subscribe first or getting into more detail. It’s a bit of “try this dish first and if you like it, I’ll tell you the recipe”. You can check out the Swagger docs on Apicultur here.
Swagger allows to generate automatically the necessary files so that the web client can show the documentation associated to the service (allowed verbs, URLs, parameters, types, descriptions, etc), but requires adding code and additional tagging while coding. However, if later on our web services are published through API Manager, the generated documentation won’t agree with the new enviroment, due to the difference in the endpoints between the original API and the published API. The only solution for this (or the only one we could think of) is only using the Swagger UI and generating the docs for each published API by hand.
In the following steps you can see how we added the Swagger doc to Apicultur.
Downloading Swagger UI
The Swagger UI can be found here and it consists of an html, js y css.
Publishing the client in the API Store
We will place the files in the API Store. We access the following location:
<AM_HOME>/repository/deployment/server/jaggeryapps/store/site/themes/fancy/templetes
and we create a new folder called swagger, where we will place the downloaded files.
In our case, we decided to show the Swagger doc in the general info page of the API, in the overview tab. This is the template for this tab:
<AM_HOME>/repository/deployment/server/jaggeryapps/store/site/themes/fancy/templetes/api/overview/templete.jag
Here (where we choose to show the docs) we add the following HTML layers that are the ones Swagger will use to load the docs content.
<div id=”message-bar”> </div><div id=”swagger-ui-container”>
If our API Store works with http and https protocol, we’ll need to create a new variable in template.jag, called “discoveryUrl” where we will keep the value depending on the used protocol:
<%
var discoveryUrl;
if (request.isSecure()){
discoveryUrl = jagg.getMappedUrl("/site/pages/api-docs/"+ api.name + "-" + api.version +"/api-docs.json");
}else{
discoveryUrl = jagg.getMappedUrl("/site/pages/api-doc/"+ api.name + "-" + api.version +"/api-docs.json");
}
%>
We’ll descibe the usefulness of this variable later on.
In order to include all the necessary js and css we’ll access the initializer on the Overview page:
<AM_HOME>/repository/deployment/server/jaggeryapps/store/site/themes/fancy/templetes/api/overview/initializer.jag
In here, we have to add all the necessary js and css:
jagg.addHeaderJS("api/api-info", "api-info1", "templates/swagger/lib/jquery-1.8.0.min.js");
jagg.addHeaderJS("api/api-info", "api-info2", "templates/swagger/lib/jquery.slideto.min.js");
jagg.addHeaderJS("api/api-info", "api-info3", "templates/swagger/lib/jquery.wiggle.min.js");
jagg.addHeaderJS("api/api-info", "api-info4", "templates/swagger/lib/jquery.ba-bbq.min.js");
jagg.addHeaderJS("api/api-info", "api-info5", "templates/swagger/lib/handlebars-1.0.rc.1.js");
jagg.addHeaderJS("api/api-info", "api-info6", "templates/swagger/lib/underscore-min.js");
jagg.addHeaderJS("api/api-info", "api-info7", "templates/swagger/lib/backbone-min.js");
jagg.addHeaderJS("api/api-info", "api-info8", "templates/swagger/lib/swagger.js");
jagg.addHeaderJS("api/api-info", "api-info9", "templates/swagger/swagger-ui.js");
jagg.addHeaderCSS("api/api-info", "api-info10", "templates/swagger/css/screen.css");
jagg.addHeaderCSSCode("api/api-info", "api-info11", ".swagger-ui-wrap {max-width: 960px;margin-left: auto;margin-right: auto;}.icon-btn {cursor: pointer;}#message-bar {min-height: 30px;text-align: center;padding-top: 10px;}.message-success {color: #89BF04;}.message-fail {color: #cc0000;}");
In addition, we have to add a js made by hand. This js file must include the function that will be executed once the site is loaded and that will render the html code in order to show a nice-looking documentation.
<script type=”text/javascript”>
We’ll explain now the values and attributes that have been modified in relation to the value that Swagger had by default:
- supportHeaderParams: we changed the value to
true
so that Swagger could sent our application token from API Manager and therefore test the response of the API. - discoveryUrl: it carries the URL of the JSON file that contains the docs info that will be shown by the Swagger client.
- headers: Here we add our application token if we want that users can not only see the documentation but also test the API by themselves.
Generating the docs for each API
In order to have and display the doc for every API without having to modify the internal code of the API Store, it suffices to follow the next steps:
Creating a directory to keep the docs
In the folder
<AM_HOME>/repository/deployment/server/jaggeryapps/store/site/pages
we’ll create two new folders called “api-docs” and “api-doc”, where we’ll keep the files for each API depending of the protocol we are using (http, https). The content of these folders will be the same, although there are two minor details that must be taken into account and that we will explain later on.
Creating a directory for each API
For every API we want to document, we’ll create a subfolder called “NameAPI-Version” in the “api-docs” directory. For instance, if I have and API in the API Store called “BasicOperations” and its version is 1.0, he folder to be created is “BasicOperations-1.0”.
Inside of this folder we’ll place the necessary files:
- api-docs.json: It’s the main file and contains links to the to the files of the different URLs.
- archivoapi: It contains the doc for all the methods allowed by the URL, parameters, type, descriptions, etc.
For our “BasicOperation” API we would have the following api-docs.json:
{
"apiVersion":"1.0",
"swaggerVersion":"1.1",
"basePath":"https://mistoreapimanager:9443/site/pages/",
"apis":[
{
"path":"/api-docs/BasicOperations-1.0/add",
"description":"This methods add to number together"
},
{
"path":"/api-docs/BasicOperations-1.0/substract",
"description":"Substract one number from another"
}
]
}
In this example, we have two different URLs for the API, and therefore we’ll have two files in order to describe each of them (one for “add” and another for “substract”). We show how the “add” file would look like (the “substract” file would look alike with the necessary modifications).
For further info concerning these files please check API Declaration, Resource Listing, Parameters y Data Types .
File “add”:
{
"apiVersion":"1.0",
"swaggerVersion":"1.1",
"basePath":"https://mistoreapimanager:9443",
"resourcePath":"basicoperations/1.0/add",
"apis":[
{
"path":"basicoperations/1.0/add/{parameter1}/{parameter2}",
"description":"Adding operation",
"operations":[
{
"httpMethod":"GET",
"summary":"It adds to numbers",
"notes":"This API returns the result of adding the two parameters",
"responseClass":"Result",
"nickname":"getAdd",
"parameters":[
{
"name":"parameter1",
"description":"First number to be added",
"paramType":"path",
"required":true,
"allowMultiple":false,
"dataType":"long"
},
{
"name":"parameter2",
"description":"Second number to be added",
"paramType":"path",
"required":true,
"allowMultiple":false,
"dataType":"long"
}
],
"errorResponses":[
{
"code":401,
"reason":"Unauthorized"
}
]
}
]
}
],
"models":{
"Result":{
"id":"Result",
"properties":{
"result":{
"type":"long"
}
}
}
}
}
Creating the copy of each API for the other protocol
Once the doc for our API is done, we can copy the entire folder into the “api-doc” directory and change the content of the files inside, changing the protocols in the URLs (and the port, if appropriate) from https to http. It will also be necessary to change the path from “/api-docs/” to “/api-doc/”.