Current version: beta-0.3.3
Generate RESTful API documentation from GO source files into the OpenAPI v3.0.2 specification (formal Swagger 2.0 Specification).
- APIDoc
- API Annotation in Comments
- Tips
- APIDoc CLI
- About the Project
- Contributing
- License
APIDoc extracts the API documentation annotation from your GO source files, recursively resoles struct references, and it generates the YAML OpenAPI v3.0.2 spec. file, which could be tested in the Swagger Editor and quickly integrated with Swagger UI.
The generator is also able to read gorilla/mux Handler and HandlerFunc func signature to automatically generate the @router
tag, and @param
tag/s. See gorilla/mux Handler Functions.
Note: It does not generate/support all OpenAPI v3.0.2 blocks, the tool handles just a subset required by our internal needs, it might be extended if there will be high demand on extension, or if anyone would like to contribute.
-
Add annotation into your API source code files, See API Annotation in Comments.
-
Get the APIDoc by using:
go get -u github.com/spaceavocado/apidoc
This will create a binary in your $GOPATH/bin folder called
apidoc
(Mac/Unix) orapidoc.exe
(Windows). -
Now you can run
apidoc
command from your shell.Make sure that $GOPATH/bin is in your Environment Variables:
-
Linux:
export PATH=$PATH:$GOPATH/bin
Note: assumption that your have correctly set $GOPATH env. variable.
-
Windows: "Control Panel" > "System" > "Edit the system environment variables" > "Advanced" > "Environment Variables" > "Path" > "Edit". and add the directory.
-
-
Run
apidoc
in the your project's root folder. This will extract and process your annotation and it generates the output YAML file.apidoc -m main.go -e handler -o docs/api
Note: the example shows the default flag values, for more details, See APIDoc CLI.
-
Preview the documentation in the Swagger Editor, i.e. put the openapi.yaml content into the editor.
An API annotation is represented as an code comment starting with @ symbol followed by documentation tag and it value or parameters. Examples:
// @title Example RESTful API
, tag title with value "Example RESTful API"// @server api.domain.com/v3 Production
, tag server with params: "api.domain.com/v3", "Production"
The the value of the tag or the last parameter of the tag captures the multiline comments, example:
// @desc Lorem ipsum dolor sit amet, consectetur adipiscing
// elit. Nullam rhoncus magna nunc, in faucibus metus pulvinar
// et. Mauris pellentesque
The value of desc tag is captured as: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam rhoncus magna nunc, in faucibus metus pulvinar et. Mauris pellentesque"
// @server api.domain.com/v3 Lorem ipsum dolor sit amet, consectetur
// elit. Nullam rhoncus magna nunc.
The last parameter, description of the server tag is captured as: "Lorem ipsum dolor sit amet, consectetur elit. Nullam rhoncus magna nunc."
This section should be located in the main file, passed to the APIDoc CLI in -m flag (defaults to main.go).
Note: () within Annotation indicates an annotation parameter captured by the generator.
Annotation | Description | OpenAPI Spec. | Example |
---|---|---|---|
title (value) | REQUIRED. The title of the application. | https://swagger.io/specification/#infoObject field: title | // @title Example RESTful API |
desc (value) | A short description of the application. | https://swagger.io/specification/#infoObject field: description | // @desc An example of publicly accessible API |
ver (value) | REQUIRED. The version of the OpenAPI document | https://swagger.io/specification/#infoObject field: version | // @ver 1.0.0 |
terms (value) | A URL to the Terms of Service for the API. | https://swagger.io/specification/#infoObject field: termsOfService | // @terms https://domain.com/api/terms |
contact.name (value) | The identifying name of the contact person/organization. | https://swagger.io/specification/#contactObject field: name | // @contact.name API Support |
contact.url (value) | The URL pointing to the contact information. | https://swagger.io/specification/#contactObject field: url | // @contact.url https://domain.com/api/support |
contact.email (value) | The email address of the contact person/organization. | https://swagger.io/specification/#contactObject field: email | // @contact.email [email protected] |
lic.name (value) | The license name used for the API. | https://swagger.io/specification/#licenseObject field: name | // @lic.name Apache 2.0 |
lic.url (value) | A URL to the license used for the API. | https://swagger.io/specification/#licenseObject field: url | // @lic.url https://www.apache.org/licenses/LICENSE-2.0.html |
server (url) (description) | An object representing a Server Note: There might be many @server tags within the main section. |
https://swagger.io/specification/#serverObject | // @server api.domain.com/v3 Production |
// @title An example authentication API
// @desc Publicly accessible authentication REST API.
// @terms https://domain.com/docs/api/terms
//
// @contact.name API Support
// @contact.url https://domain.com/contact
// @contact.email [email protected]
//
// @lic.name Apache 2.0
// @lic.url https://www.apache.org/licenses/LICENSE-2.0.html
//
// @ver 1.0
// @server https://auth.domain.com/v3 Production API
// @server https://auth.dev.domain.com/v3 Development API
func main() {}
An endpoint is being considered as a API comment annotation block found within any file located inside the endpoints root folder, passed to the APIDoc CLI in -e flag (defaults to ./).
For better performance is highly recommended to pass the endpoints root folder as a flag to the CLI to avoid unnecessary file processing.
Note: () within Annotation indicates an annotation parameter captured by the generator.
Annotation | Description | OpenAPI Spec. | Example |
---|---|---|---|
summary (value) | A short summary of what the operation does. | https://swagger.io/specification/#operationObject field: summary | @sumamry Lorem ipsum dolor |
desc (value) | A verbose explanation of the operation behavior. | https://swagger.io/specification/#operationObject field: description | @desc Lorem ipsum dolor sit amet, consectetur adipiscing eli |
id (value) | Unique string used to identify the operation. The id MUST be unique among all operations described in the API. The operationId value is case-sensitive. | https://swagger.io/specification/#operationObject field: operationId | // @id login |
tag (array) | A list of tags for API documentation control. Tags can be used for logical grouping of operations by resources or any other qualifier. Note: Comma separated value, or a single value. |
https://swagger.io/specification/#operationObject field: tags | // @tag User // @tag User, Authentication |
accept (array) | A list of accepted request content mime types See Mime Types Annotation |
n/a | // @accept json // @accept application/json, application/x-www-form-urlencoded |
produce (array) | REQUIRED. A list of supported content response mime types See Mime Types Annotation |
n/a | // @produce json // @produce application/json, application/x-www-form-urlencoded |
param (name) (in) {(type)} (required) (description) | Describes a single operation parameter. See Param Tag Note: There might be many @param tags within the endpoint block. |
https://swagger.io/specification/#parameterObject | // @param token path {string} true Security Token |
body (reference) | Describes a single request body. See Body Tag |
https://swagger.io/specification/#requestBodyObject | //@body model.Login |
swrap (reference) (field pointer) | Success object wrapper. If this tag is set, any success response object is being wrapped with this object on the desired pointer field See Wrapper Tag |
n/a | // @swrap response.Success |
success (code) {(type)} (reference or empty) (description) | REQUIRED. Describes a single success response from an API Operation. See Response Tag |
https://swagger.io/specification/#responseObject | // @success 200 {object} response.Success OK // @success 200 {string} OK |
fwrap (reference) (field pointer) | Failure object wrapper. If this tag is set, any failure response object is being wrapped with this object on the desired pointer field See Wrapper Tag |
n/a | // @fwrap response.Error |
failure (code) {(type)} (reference or empty) (description) | Describes a single failure response from an API Operation. See Response Tag |
https://swagger.io/specification/#responseObject | // @failure 401 {object} response.AuthError Unauthorized // @failure 401 {string} Unauthorized |
subrouter (value) | Name of the subrouter used for this endpoint. See gorilla/mux Subrouter |
n/a | // @subrouter user [post] |
router (path) [(method)] | REQUIRED. Describes the operations available on a single path, i.e. endpoint URL See Path Tag |
https://swagger.io/specification/#pathItemObject | // @router /login [post] |
Annotation: param (name) (in) {(type)} (required) (description)
This section contains detailed information about the param tag
- The name of the parameter. Parameter names are case sensitive.
- If
in
is "path", the name field MUST correspond to the associated router url parameter, e.g.:// @param token path {string} true Security token
must match with// @router /auth/{token} [get]
- The location of the parameter. Possible values are "query", "header", "path" or "cookie".
- the outer "{}" are used just as visual separators of type field, i.e. their are not required.
E.g.
// @param token path {string} true Security token
=// @param token path string true Security token
- Param tag does not support struct type, just base go types, See Type Mapping
- Array annotation:
{[]string}
,{[]int}
, etc.
Annotation: body (reference)
-
go structure used as request model, example:
// @body model.Login
// Login struct located in "model" package, // referenced in the go file where the endpoint // annotation is set type Login struct { // User's email address Username string `json:"username"` Password string }
will be resolved as:
schema: type: object parameters: username: type: string description: User's email address password: type: string
-
The reference structure is being resolved recursively, i.e. it might contain fields referencing other go struct.
-
See Struct Annotation for more details.
Annotation: swrap (reference) (pointer field), fwrap (reference) (field pointer)
If this tag is set, any success/failure response object is being wrapped with this object on the desired pointer field. This is useful if you are using a generic API response object with various data field.
type APISuccess struct {
Status string `json:"status"`
Data interface{} `json:"data"`
}
type Profile struct {
Firstname int `json:"firstname"`
Lastname string `json:"lastname"`
}
// @swrap APISuccess data
and // @success 200 {object} Profile OK
will produce:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
status:
type: string
data:
schema:
$ref: "#/components/schemas/Profile"
- The reference structure is being resolved recursively, i.e. it might contain fields referencing other go struct.
- See Struct Annotation for more details.
Annotation: success (code) {(type)} (reference or string) (description), failure (code) {(type)} (reference or string) (description)
- Any valid HTTP reponse code
- The outer "{}" are used just as visual separators of type field, i.e. their are not required.
E.g.
// @success 200 {string} string OK
=// @success 200 string string OK
- Supported: object, string
- if set to object, the next parameter expected is reference
- if set to string, next parameter is skipped (reference)
- Reference response go struct
- Array annotation:
{[]response.Car}
, etc. - The reference structure is being resolved recursively, i.e. it might contain fields referencing other go struct.
- See Struct Annotation for more details.
Annotation: router (path) [(method)]
- It might contain the "path" parameters, it this format:
/login/{token}
where token is the name of param defined in the Param Tag.
- HTTP method
- The outer "[]" are used just as visual separators of method field, i.e. their are not required.
E.g.
// @router /login [post]
=// @router /login post
- It might contain an array of methods, e.g.:
[post, put]
// Login request
// @summary Login user
// @desc Authentication request
// @id login
// @tag Authentication
// @accept json, application/x-www-form-urlencoded
// @produce json
// @body model.Login
// @swrap response.Data data
// @success 200 {object} request.Token OK
// @failure 401 {object} response.Error Unauthorized.
// See error code and error message for more details.
// @failure 500 {string} Internal Server Error
// @router /login [post]
func handler(w http.ResponseWriter, r *http.Request) {}
// @summary Activate user
// @desc User activation via the token request.
// @id activate
// @tag Registration
// @param token path {string} true Activation token
// @produce json
// @success 200 {string} OK
// @failure 500 {string} Internal Server Error
// @router /registration/activate/{token} [get]
func handler(w http.ResponseWriter, r *http.Request) {}
// Handlers with passed gorilla mux router
//
// In this example the @router tag is being resolved
// from the HandleFunc or Handle gorilla *mux.Router func.
// @param tags ara also resolved from the func path string.
//
// These tags will be extracted automatically:
// @router /person/{id} [get]
// @param id path {string} true
func Handlers(r *mux.Router) {
// GetPerson handler
// @summary Person
// @desc Get person by ID.
// @id person
// @tag Person
// @produce json
// @success 200 {object} Person OK
// @failure 500 {string} Internal Server Error
r.HandleFunc("/person/{id:[0-9]+}", GetPerson).Methods("GET")
}
@router
tag and @param
tags could automatically resolved if the endpoint annotation is placed above the gorilla/mux Handler or HandlerFunc function:
// GetPerson handler
// @summary Person
// @desc Get person by ID.
// @id person
// @tag Person
// @produce json
// @success 200 {object} Person OK
// @failure 500 {string} Internal Server Error
r.HandleFunc("/person/{id:[0-9]+}", GetPerson).Methods("GET")
Automatically resolved tags will be be:
@router /person/{id} [get]
@param id path {string} true
- This process is skipped if the endpoint annotation contains the
@router
tag - If the endpoint annotation contains a
@param
tag found in the func path parameter, it is not being overwritten by the this process nor double annotated. - Please see gorilla/mux Subrouter section for more information how to work with gorilla/mux subrouters.
An endpoint can use subrouter
tag to connect a endpoint with the subrouter to resolve the final endpoint URL.
Annotation | Description | Example |
---|---|---|
router (name) | Name of the subrouter. | // @router account |
subrouter (name) | Name of the parent subrouter. | // @subrouter admin |
The annotation must be placed above the gorilla.mux Subrouter method anywhere within the Main file or in any file within the endpoints root folder.
// @router admin
r.PathPrefix("/admin").Subrouter()
// @router user
// @subrouter admin
r.PathPrefix("/user").Subrouter()
// @summary List of users
// @produce json
// @success 200 {object} Person OK
// @subrouter user
r.HandleFunc("/list", GetPersonList).Methods("GET")
The URL resolved for the "List of users" endpoint will be
/admin/user/list
Mime Type | Annotation |
---|---|
text/plain | text, text/plain |
text/html | html, text/html |
text/xml | xml, text/xml |
application/json | json, application/json |
application/x-www-form-urlencoded | form, application/x-www-form-urlencoded |
multipart/form-data | multipart, multipart/form-data |
application/vnd.api+json | json-api, application/vnd.api+json |
application/x-json-stream | json-stream, application/x-json-stream |
application/octet-stream | octet-stream, application/octet-stream |
image/png | png, image/png |
image/jpeg | jpeg, image/jpeg |
image/jpeg | jpg, image/jpeg |
image/gif | gif, image/gif |
type Profile struct {
// User's email
Username string `json:"username" required:"true"`
Status UserStatus `apitype:"int"`
}
type UserStatus int
- Comment above the field is being captured as field "description"
json:"x"
overrides the field nameapitype:"x"
overrides the field typerequired:"true"
marks the field as required
Go types are being converted into OpenAPI accepted format
go Type | Converted Type |
---|---|
byte | integer |
rune | integer |
int | integer |
int8 | integer |
int16 | integer |
int32 | integer |
int64 | integer |
uint | integer |
uint8 | integer |
uint16 | integer |
uint32 | integer |
uint64 | integer |
uintptr | integer |
float32 | number |
float64 | number |
bool | boolean |
Last parameter of any tag is could spread over multiple lines, e.g.:
// @desc Lorem ipsum dolor sit amet, consectetur adipiscing
// elit. Nullam rhoncus magna nunc, in faucibus metus pulvinar
// et. Mauris pellentesque enim justo
// @failure 500 {string} Lorem ipsum dolor sit amet, consectetur
// adipiscing elit. Nullam rhoncus magna nunc, in faucibus metus
// pulvinar et. Mauris pellentesque enim justo.
Use [] annotation in from of the reference.
// @body []request.Person
// @success 200 {object} []response.Person OK
An endpoint, with the same URL could be declared separately with different methods, and the generator will properly group them.
// @summary Get User
// @param id path {int} true User ID
// @produce text
// @success 200 {string} OK
// @router /user/{id} [post]
// ...
// @summary Delete User
// @param id path {int} true User ID
// @produce text
// @success 200 {string} OK
// @router /user/{id} [delete]
will produce
/user/{id}:
get:
summary: Get User
parameters:
- name: id
description: User ID
in: path
required: true
schema:
type: integer
responses:
"200":
description: OK
content:
plain/text:
schema:
type: string
delete:
summary: Delete User
parameters:
- name: id
description: User ID
in: path
required: true
schema:
type: integer
responses:
"200":
description: OK
content:
plain/text:
schema:
type: string
Run the apidoc -h
to all flags and commands:
API Documentation Generator
Usage:
[flags]
[command]
Available Commands:
help Help about any command
version Show the APIDoc version
Flags:
-e, --endpoints string Root endpoints folder (default "./")
-h, --help Help for this command
-m, --main string Main API documentation file (default "main.go")
-o, --output string Documentation output folder (default "docs/api")
-v, --verbose Show generation warnings
Use " [command] --help" for more information about a command.
This project was inspired by swaggo/swag, designed mainly to handle our API documentation needs, i.e. add support for response wrappers, generate OpenAPI v3.X documentation. Any feedback, contribution to this project is welcomed.
The project is in a beta phase, therefore there might be major changes in near future, the annotation should stay the same, though.
When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change.
- Fork it
- Create your feature branch (
git checkout -b ft/new-feature-name
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin ft/new-feature-name
) - Create new Pull Request
Please make an issue first if the change is likely to increase.
APIDoc is released under the Apache 2.0 license. See LICENSE.txt