OpenAPI (formerly known as Swagger) is the more popular protocol for defining HTTP APIs. However, the OpenAPI definition file is in a machine-friendly format that is not easy to write and read. Here is a method to generate OpenAPI definition files based on Go code using go-swagger. This method uses only Go code to define the API, and does not force the Server or Client to use Go as well.
Currently go-swagger
can only generate definitions in OpenAPI 2.0 format. This is also the format that is widely used now. go-swagger
will support OpenAPI 3.0 in the future.
This article assumes familiarity with Go syntax and only explains the extensions to go-swagger
in detail.
Suppose you want to create a set of APIs for a pet store that supports defining pets. This article shows how to use Go to define this API.
Although go-swagger
does not require the use of a Go project, it is recommended to create a separate Go project for the API to facilitate the use of completions and code highlighting.
The first step is to define the basic information about the API, such as the name of the API, the protocol, the supported serialization formats, the base path, and some security information. This information is defined in the petstore.go
file.
|
|
The package description, according to Go’s specification, is to start with Package petstore
. The remainder of that line, which is The API of the pet store.
will be used as the title
part of OpenAPI, and the rest of the non-go-swagger
defined comments will be used as the description
of OpenAPI.
Note: If the package description does not contain a description
section, go-swagger
will use the first line of what would otherwise be the title
section as the description
and leave the title
blank. The OpenAPI file defined this way does not conform to the specification. So please write the two descriptions in full.
Starting at the Version:
line is the definition of go-swagger
. This section defines the rest of the base content of the generated OpenAPI file. The specific options available can be found in swagger:meta. The last line swagger:meta
indicates that this comment is used in go-swagger
to generate the base information.
The next two lines go:generate
are used to generate the OpenAPI file. To ensure that no executable is missing during execution, go run github.com/go-swagger/go-swagger/cmd/swagger@latest
is used to call go-swagger
. If you can guarantee that the execution environment has go-swagger
installed, the two lines go run ...
can be simplified directly to swagger
. This simplification will improve the speed of execution when generating.
To install go-swagger
, you can refer to official website. If you have a Go environment, you can install it directly via go install github.com/go-swagger/go-swagger/cmd/swagger@latest
. Note that you need to add $GOPATH/bin
to $PATH
for easy execution.
The first line generate spec -o openapi.yaml
will generate the OpenAPI file based on the contents of the current directory. The second line validate openapi.yaml
will verify that the OpenAPI file is compliant.
With this file, you can generate the OpenAPI file by executing go generate .
to generate the OpenAPI file. The execution will generate:
|
|
We haven’t defined any APIs yet, so the paths
field is empty. We will add this field later step by step.
After that, define the API related to the Pet instance in the pet.go
file.
First define the Pet
structure.
|
|
where NewPet
is used to create and modify Pet data, and Pet
is used to display Pet data. The two structures have some nuances, such as NewPet
will not have ID
information, and Pet
does not need to define input restrictions. In simple scenarios, the structures can be combined into one structure, or NewPet
can be embedded anonymously in Pet
to simplify the structure.
swagger:model
is processed by go-swagger
as a predefined structure and the definitions are placed in definitions
. This structure will be reused across multiple API methods.
go-swagger
will generate the corresponding types based on the type of the Go structure. The annotation of each field can specify more detailed value constraints, such as min length: 1
and max length: 64
in the example, which agree that the length of the corresponding field string should be between [ 1, 64]
. Further semantic constraints on the string values can also be made using swagger:strfmt
.
In order to return another structure when handling errors, it is also necessary to define the error structure.
Simple structures can be used without writing all the information, even without marking swagger:model
. go-swagger
will automatically find the corresponding structure definition based on the definition of the method afterwards.
Once the structure for processing is defined, the specific operation methods can be defined. To cover the widest range of cases, here is an example of how to update a Pet
method.
swagger:route
is used to define a specific API method in the format swagger:route <method> <url> <tag> ... <operation id>
. There can be zero or any number of tags
, giving the method a number of tags. No matter how many tags
there are, the last parameter operation id
is the name of the method. This method name needs to be unique in an API definition file.
Specifically in the example, swagger:router POST /pets/{pet_id} pet CreatePet
means the following.
- Follow the common API principle of defining the update method on the
POST /pets/{pet_id}
endpoint.- The path has an input parameter
pet_id
.
- The path has an input parameter
- Add the
pet
tag to this method. - The method name is
CreatePet
.
This is followed by the method description information.
responses
is the return information that defines the go-swagger
, and can be structured differently depending on the HTTP Code. The example returns a PetReply
structure when the operation is normal, i.e. Code 200
, and an ErrorReply
structure in other cases.
Let’s put aside the output structure and look at how to define the input structure.
swagger:parameters
is used to define an input structure in the format swagger:parameters <operation id> <operation id> ...
. where operation id
is the name of the method that uses this input structure. Note that it is possible to have multiple input structures used on a single method, such as the example where both structures reference UpdatePet
. Because the input to a method is not only the HTTP Post message, but also the information inside the URL and possibly even the Header. In order to reuse these structures, go-swagger
can define different parts of the input into different structures and reference them to the same method.
In the example, PetIDArg
defines the path parameter pet_id
by in: path
, where pet_id
is defined by json: "pet_id"
. Another structure NewPetArg
defines the Post message structure NewPet
via in: body
, where NewPet
is one of the structures described above.
This is followed by the output structure.
swagger:response
is used to define an output structure. Its name is the same as responses
defined by swagger:route
. in: body
indicates the corresponding field for the returned HTTP message.
This completes the definition of Pet’s update method. It also explains most of the contents of go-swagger
. You can directly execute go generate .
or swagger generate spec
to see the output. More details on using go-swagger
to generate spec files can be found on the official website.
As an example, the following pet.go
file gives all the definitions for the Pet operation. Together with the previously mentioned petstore.go
file, it can be used directly to generate the OpenAPI definitions for petstore
.
|
|