README ¶
Swaggogen
Swaggogen is a tool for extracting Go (golang) type information from an application and combining it with code comments to generate a Swagger/OpenAPI 2.0 specification document.
Usage
Swaggogen takes one parameter, pkg
. This parameter should be the package path
of the application you want to document.
Example:
swaggogen -pkg github.com/foo/bar
The application will generate the Swagger/OpenAPI document as JSON and print it to stdout.
It is acknowledged that there are some unavoidable warnings that are printed to stderr, and it's not pretty. The author(s) know this, and it is preferred that end users be aware of the limitations as they exist. Because these warnings are printed to stderr (not stdout), they should not affect the output of any JSON. Furthermore, in practical settings, these warnings have never indicated a failure to generate a complete Swagger specification document. Please feel free to submit a merge request as appropriate.
Optional Flags
profile
string
This is for programmers only.
This flag accepts the path to a file name where profiling details will be stored. Profiling details can be reviewed using something like the following command:
go tool pprof swaggogen swaggogen.prof
ignore
string
This flag accepts a comma-separated list of packages that you want to ignore. This is useful if, for example, you import a package that has annotations that shouldn't be in your final spec.
naming
string
This flag accepts one of full, partial, or simple.
When using the value of full, the whole Go package path is used to generate the Swagger model name from the Go type. To remain compatible with the Swagger spec, the slashes are replaced by periods.
When using partial, the Swagger model names are comprised of the Go package name and the Go type name, much in the same way that they would be referenced in Go code.
When using simple, the Swagger model name is simply the name of the corresponding Go type. No package information is used.
As you may imagine, the likelihood of name collisions increases with each step in this spectrum. There are no warnings in the code to protect you from collisions.
Recognized Comment Blocks
Swaggogen picks up on three kinds of comment blocks, Tag Definitions, Operation Definitions, and API Definitions. There's no reason you can't mix these comment blocks, but your results may vary. The only blocks it makes sense to mix are Tag Definition and API Definition blocks. The only reason these two blocks are recognized separately is for convenience.
Each comment block is processed as a series of sections. Each section begins with a recognized tag, and then a body. For compatibility with Godoc, it is recommended that the body be indented compared to the section tag.
An example section:
/*
OpenAPI Query String Parameters:
world string required World UUID
user string optional User UUID
x int optional X-coordinate for blind query
y int optional Y-coordinate for blind query
w int optional Width of query area
h int optional Height of query area
*/
The section ends when another tag is recognized.
If you want to add comments to a comment block that is likely to be processed by Swaggogen, add those comments to the top of the block. Section processing only begins when a section is actually detected.
Because of the complexity of the Swagger specification and the variety of information that can be absorbed by the specification, I regret to inform you that each section is processed in its own way. Hopefully the layouts of each section makes enough practical sense to be practical. If you can suggest a better layout for either the comment blocks or the sections, please put in a merge request or contact me.
those that specifically contain these tags: "OpenAPI Tag:", "OpenAPI Path:", and "OpenAPI API Title:". These tags are not case sensitive. If you combine the comment blocks, Swaggogen will pick up the various tags in the comment blocks just the same.
Swaggogen observes two kinds of code blocks, API definitions and Route Definitions. The lines that are parsed for use in the Swagger document must contain a keyword, which is a marker beginning with an '@'. The format of each line depends on the keyword.
These annotations are intended to be compatible with Yuriy Vasiyarov's project, found at http://github.com/yvasiyarov/swagger.
For the sake of simplicity, a Route Definition combines the necessary information to generate Paths and Operations in Swagger terminology. For this reason, throughout the documentation, a Route will be in reference to a Swagger Operation in combination with its respective Path.
API Definitions
API Definitions support the following tags:
OpenAPI API Title:
OpenAPI API Description:
OpenAPI API Version:
OpenAPI Base Path:
The OpenAPI API Title:
is required by the Swagger specification, and is used
as a trigger for detecting API Definition comment blocks. So, make sure you use
that tag to make things work. Multiple API definitions are allowed, but they
will be combined without any guarantees of precedence.
OpenAPI API Title:
The OpenAPI API Title:
tag defines the title of your API. The first line in
the section body is accepted as your title.
Example:
OpenAPI API Title:
My REST API
OpenAPI API Description:
The OpenAPI API Description:
tag defines the description of your API. Any text
in the body of the section is accepted as your description.
Example:
OpenAPI API Description:
My API is awesome!
OpenAPI API Version:
The OpenAPI API Version:
tag defines the API version of your application. The
body of the section is used for the version number. Any combination of
contiguous printable characters is acceptable.
Example:
OpenAPI API Version:
1.0.0-test
OpenAPI Base Path:
The OpenAPI Base Path:
tag defines the base path of your API. Per the Swagger
specification, this path is prepended to all paths defined in the paths of your
specification. An acceptable path (URL component) should begin with a forward
slash and contain letters, numbers, periods, slashes, hyphens, and underscores.
Example:
OpenAPI Base Path:
/api/v1
Route Definitions
Route Definitions are comprised of lines beginning with the following keywords:
OpenAPI Content Type:
OpenAPI Description:
OpenAPI Method:
OpenAPI Path:
OpenAPI Query String Parameters:
OpenAPI Request Body:
OpenAPI Responses:
OpenAPI Summary:
OpenAPI Tags:
Any comment block containing the @Router
tag is considered an Route
Definition. Multiple API route definitions are allowed.
In various Route Definition sections, a type must be specified. A type can
be a Swagger-defined primitive type (int, string, boolean, etc.) or a Go type.
A specification of nil
is understood to mean 'no type'.
If the type specification should be a Go type, it must be specified exactly how
it would be referenced in code. For example, if the struct type Foo
is in the
local package, then the argument can be referenced simply with Foo
. If it is
defined in another package that is imported with an alias
(import f "/github.com/jackmanlabs/fooness"
), then the type argument should be
referenced with the alias, f.Foo
.
A complete example:
/*
OpenAPI Path:
/api/foos
OpenAPI Method:
GET
OpenAPI Query String Parameters:
world string required World UUID
user string optional User UUID
x int optional X-coordinate for blind query
y int optional Y-coordinate for blind query
w int optional Width of query area
h int optional Height of query area
OpenAPI Request Body:
nil
OpenAPI Response Body:
[]types.Foo
OpenAPI Description:
This endpoint returns all of the foos that belong to the user and world
specified by the query string parameter.
The `world` parameter is required in all uses.
The `user` parameter returns all foos owned by that user. If the calling
player has permission to view all foo information, then that information
will be returned. Otherwise, only a subset of foo information is
returned. Use of this parameter is the recommended way to get the calling
user's foos. Use of this parameter takes precedence over the use of the
`x`, `y`, `w`, and `h` parameters.
Similar to the tiles endpoint (`/api/tiles [GET]`), the `x`, `y`, `w`, and
`h` parameters control the retrieval of all the foos in a specific area
of the map. Unless specified, the values for these parameters are assumed to
be zero. If `w` and `h` are zero, then only one foo is returned (if it
exists at the coordinates provided). The maximum values accepted for `w` and
`h` will be 1000, and values exceeding 1000 will be quietly accepted as
1000.
In all circumstances, a set (array) is returned regardless of the quantity
of foos returned.
*/
func HandleFoosGet(w http.ResponseWriter, r *http.Request, userId string) error {}
OpenAPI Content Type:
The OpenAPI Content Type:
tag defines the set of MIME types that this Route
consumes and produces; symmetry in this regard is assumed.
The body of the section should contain a list of content types, one per line.
Admittedly, this tool takes some liberties and simply checks for the presence
of json
or xml
. Accordingly, the Produces and Consumes properties
of the corresponding Swagger Operation object is populated with standard
application/json
and application/xml
strings. This behavior will likely
change as greater sophistication is required. Feel free to submit a merge
request with more sophisticated behavior.
Example:
OpenAPI Content Type:
json
xml
OpenAPI Description:
The OpenAPI Description:
tag defines a human readable description for the
Swagger Operation. Everything in the section body is assumed to be the
description.
Example:
OpenAPI Description:
This route is a good one.
OpenAPI Method:
The OpenAPI Method:
tag specifies the HTTP method of this endpoint. For most
people, this will be one of GET
, PUT
, POST
, or DELETE
. As of right now,
the method is not validated, and can be pretty much any single word. Also, the
method is not case sensitive, but will be made all-caps in the output for the
sake of common convention.
Example:
OpenAPI Method:
GET
OpenAPI Path:
The OpenAPI Path:
tag defines the path of the operation. Swaggogen expects
this to be a single line with the path of the operation, not including the base
path.
OpenAPI Query String Parameters:
The OpenAPI Query String Parameters:
tag allows you to specify the query
string parameters of the operation.
Each line of the body may contain a single
parameter. Each line must contain four fields, in order: name, type, necessity,
and description. Each of the first three fields must not contain any spaces. Any
text after the first three fields is considered to be the description.
Quotations (with double quote marks, "
) around the description are ignored.
The necessity of the parameter (required vs. optional) is specified in the third
field. A required field must have required
in this field. Virtually any other
word is understood to mean 'not required', but I encourage optional
because it
makes for some pretty columnar formatting.
Example:
OpenAPI Query String Parameters:
world string required World UUID
user string optional User UUID
x int optional X-coordinate for blind query
y int optional Y-coordinate for blind query
w int optional Width of query area
h int optional Height of query area
OpenAPI Request Body:
This tag specifies the type of the request body. This tag is optional, but if
you want to explicitly specify 'no body', use nil
. No other information is
required.
Example:
OpenAPI Request Body:
[]foo.Bar
OpenAPI Responses:
The OpenAPI Responses:
tag defines any number of responses that may be
generated by the endpoint.
One response should be given per line of the section body. Each line must contain three fields: HTTP status code, body type, and a description.
The status code must be numeric. The body type must conform to a type as described in the section titled Route Definitions. Neither of the first two fields may contain spaces, and the description is any text following the first two fields.
OpenAPI Responses:
200 []foo.Bar Normal response, a collection of foo.Bar objects.
401 errs.Error The user is not authenticated.
OpenAPI Summary:
The OpenAPI Summary:
tag defines the summary of the operation. In previous
implementations of Swaggogen, this was called the title. To conform to the
Swagger/OpenAPI specification, it is now the summary.
The first line of the section body will be used as the summary.
Example:
OpenAPI Summary:
Search for things.
OpenAPI Tags:
The OpenAPI Tags:
tag defines the list of tags (as described in the section
Tag Definitions) that should apply to the operation. Correlation between tags
in the operations and tags defined by Tag Definitions is not validated.
Tags should be listed in the section body, one per line.
Example:
OpenAPI Tags:
Villages
Towns
Code Structure
This tool operates, at least conceptually, in three phases: detection, extraction, and generation.
During the parsing phase, the code project is scanned for comments blocks.
In the extraction phase, the comment blocks are transformed into intermediate representations, called Intermediates. Some of these Intermediates are very basic, such as the ApiIntermediate. It is comprised of parsed information and nothing else. Other Intermediates, such as the DefinitionIntermediate, require further analysis of the code, pulling struct definitions, enums, and so on from the code to create Swagger type definitions in the generation stage.
Finally, in the generation phase, the Intermediates have been fully populated, and the swagger object tree is generated. Many Intermediates have a Schema() method so that they can generate their own schema by way of interface.
Creditation
This tool was written blind with respect to other similar tools.
While this tool was originally intended to utilize the same annotations as the yvasiyarov project. The development of that code was sponsored by EMS Software, developed by Andrew Roy Jackman, and made public under the MIT license under the direction of the VP of Engineering.
The latest mode of operation, utilizing Godoc-compatible comments, is made possible with development sponsored by Scout Exchange.
Also, the availability of the OpenAPI specification models from the OpenAPI Initiative golang toolkit library, on which this project depends, is greatly appreciated.
Documentation ¶
There is no documentation for this package.
Source Files ¶
- definition_store.go
- definitions.go
- intermediate_api.go
- intermediate_definition.go
- intermediate_interface.go
- intermediate_map.go
- intermediate_member.go
- intermediate_operation.go
- intermediate_slice.go
- intermediate_tag.go
- main.go
- section.go
- swaggerization.go
- util.go
- validations.go
- validator_interface.go
- walker_comments.go
- walker_definitions.go
- walker_enums.go
- walker_imports.go