apigenie-generatorOpenAPI serversserver go
server go
Generate a Go server for the net/http router of Go 1.22 from an OpenAPI document.
From an AsyncAPI document, the command generates a Go Kafka application instead; see apigenie-generator server go (AsyncAPI).
Usage
apigenie-generator server go [...OPTIONS] INPUT_FILE
Description
The generator writes a Go package whose code uses the standard library only. Its names and layering
follow oapi-codegen (the std-http-server and
strict-server targets), so code written against one of them is easy to move to the other.
| File | Contents |
|---|---|
types.gen.go |
the types of the component schemas the operations use, and of their inline schemas |
server.gen.go |
ServerInterface, the parameters structs, ServerInterfaceWrapper, Operations, SecuritySchemes and HandlerWithOptions |
strict.gen.go |
StrictServerInterface, the request and response objects, and NewStrictHandler |
spec.gen.go, openapi.yaml |
the OpenAPI document, embedded with //go:embed (RawSpec()) |
runtime_*.gen.go |
parameter binding, validation, problem details, Nullable[T], Date, multipart helpers |
go.mod, cmd/<package>/main.go |
with layout: module (and main: true) |
There are two ways to implement the server:
ServerInterface: one method per operation receives thehttp.ResponseWriter, the request, the path parameters and a struct with the query, header and cookie parameters, bound and validated. The method decodes the body and writes the response.StrictServerInterface: one method per operation receives a request object (parameters and decoded, validated body) and returns a response object, e.g.GetPet200JSONResponse, with its status, typed headers and body.NewStrictHandlerturns it into aServerInterface.
mux := http.NewServeMux()
api.HandlerWithOptions(api.NewStrictHandler(server, nil), api.StdHTTPServerOptions{
BaseURL: "/api/v1",
BaseRouter: mux,
SecurityHandler: authenticator, // runs before parameters are bound
})
log.Fatal(http.ListenAndServe(":8080", mux))
HandlerWithOptions registers one pattern per operation, e.g. GET /pets/{petId}, so routing,
405 Method Not Allowed (with Allow) and HEAD requests are handled by http.ServeMux:
- paths ending with
/are registered as/{$}, so that they don’t match the paths below them; - path parameters whose names aren’t Go identifiers (
{pet-id}) are renamed, and parameters sharing a path segment with other text (/files/{name}.{ext}) are split out of it; - patterns
http.ServeMuxcan’t register together (it panics), such asGET /a/{x}/bandGET /a/b/{y}, are served through one pattern generalizing them, which sends each request to the most specific operation.route_conflicts: errorreports them as errors instead.
Types
- Optional properties are pointers with
omitempty; slices, maps andanystay values.optional_fields: omitzerouses values withomitzero(Go 1.24). - Optional properties that can be null are
Nullable[T], which tells absent, null and set values apart; required ones are pointers.nullable_type: pointeruses pointers for both. - Required properties that are
readOnlyorwriteOnlyare pointers, as they are absent from requests or responses. - Structs that would contain themselves hold pointers.
- Enums are defined types with constants named after the type and the value
(
PetStatusAvailable),PetStatusValues(),IsValid()andValidate(). oneOfandanyOfschemas are structs with one pointer per variant. With a discriminator, the value goes to the variant its property selects: through themapping, the name of the schema or the value the schema gives the property (const); other values go to thedefaultMappingvariant (x-defaultMappingin 3.0 and 3.1 documents), or are kept inRaw. Without a discriminator, the value goes to the first variant it decodes into without unknown properties and validates against.allOfschemas are merged into one struct; ananyOforoneOfwhose members only list required properties (anyOf: [{required: [email]}, {required: [phone]}]) is checked byValidate().additionalPropertiesare kept in anAdditionalPropertiesmap.date-timestrings aretime.Time,datestringsDate,byteandbinarystrings[]byte(files in multipart bodies).
Validation
Every type has a Validate() method checking the constraints of its schema (lengths, patterns,
bounds, multipleOf, items, properties, enums and the email, uuid, uri, hostname,
ipv4, ipv6, date, date-time and time formats). Parameters and request bodies are
validated before the handlers are called, and failures are answered with
RFC 9457 problem details listing the failed checks:
{"title":"Bad Request","status":400,"detail":"The request is not valid.",
"errors":[{"path":"limit","check":"maximum","message":"must be less than or equal to 100"}]}
DefaultErrorHandler maps errors to statuses: 400 for parameters and bodies, 413 for bodies
larger than max_body_bytes, 415 for unsupported media types, the status of a SecurityError
(401 by default) or of an error implementing StatusCode() int, and 500 otherwise.
Extensions
| Extension | Effect |
|---|---|
x-go-name |
name of the type of a schema, or of the field of a property |
x-go-type |
Go type of a schema, e.g. decimal.Decimal; with x-go-type-import: {path: ...} for its package |
x-go-type-skip-optional-pointer |
the optional property isn’t a pointer |
x-go-json-ignore |
the field gets the tag json:"-" |
x-omitempty |
true or false overrides the omitempty of the field |
x-enum-varnames, x-enumNames |
names of the enum constants |
x-enum-descriptions |
comments of the enum constants |
x-apigenie.codegen.name |
name of the type of a component schema, when it has no x-go-name |
x-apigenie.codegen.action-name |
name of the handler method of an operation without an operationId (with the default action_naming, which lists id first) |
x-apigenie.codegen.disabled |
true on an operation or its path item leaves the operation out |
x-defaultMapping |
defaultMapping of a discriminator in OpenAPI 3.0 and 3.1 documents: the schema of the values whose discriminator value isn’t mapped |
The extensions can live in an overlay for this target instead of in the document, e.g.
go.overlay.yaml:
overlay: 1.0.0
info:
title: Go types
version: 1.0.0
actions:
- target: $.components.schemas.Pet
update:
x-go-name: Animal
- target: $.components.schemas.Pet.properties.price
update:
x-go-type: decimal.Decimal
x-go-type-import:
path: github.com/shopspring/decimal
apigenie-generator server go openapi.yaml --overlay go.overlay.yaml -o out
Limitations
- Callbacks and webhooks aren’t generated, and operation and path servers are ignored: every
operation is registered below the same
BaseURL. x-internalisn’t honoured: onlyx-apigeniecodegen.disabledskips operations.text/event-streamresponses are written at once as text, so events can’t be streamed;itemSchemaisn’t read, so stream items aren’t typed (application/jsonlbodies areio.Readerstreams).Validate()doesn’t checkprefixItems,patternProperties,if/then/else,dependentRequired,dependentSchemasandunevaluatedProperties.- XML bodies are passed as streams (
io.Reader), and form or multipart responses too. - Patterns using lookaround or backreferences, which Go’s
regexppackage doesn’t support, aren’t checked (a warning says so). Patterns are compiled when first used. allOfschemas are flattened: there are no type hierarchies.- Exported names of the runtime (
Problem,Date,File,Nullable,Operation, …) are reserved: schemas with these names get numbered types, e.g.Problem2. - The input must be an OpenAPI 3.0, 3.1 or 3.2 document; convert Swagger 2.0 documents with
apigenie convert, and bundle documents referencing other files withapigenie bundle.
Options
-c, –config
Path to the configuration file to use. See the “Configuration” section for more information.
–overlay OVERLAY
Path to an OpenAPI Overlay (1.0 to 1.2) applied to the input before generating, e.g. one setting the
extensions of the “Extensions” section. Can be repeated: the overlays apply in order, after those
listed under commands.generate.server_go.overlay in the configuration file (with paths relative to
it). Warnings and errors about a value an overlay set point to the overlay.
–strict
Makes an overlay action whose target selects nothing an error (exit status 2, nothing is generated)
instead of a warning (OVERLAY:LINE:COL: action #N (TARGET) selects no nodes.).
-o, –output
Directory where the package is generated.
–package-name
Name of the Go package. Defaults to the name of the output directory (api when it isn’t a valid
package name).
–package-version
Ignored: Go packages have no version.
-p, –property NAME=VALUE
Sets a generator option (see below), e.g. -p layout=module. Options given on the command line
take precedence over the configuration file. Lists are comma-separated (-p include_tags=pets,store)
and mappings too (-p type_mappings=uuid=github.com/google/uuid.UUID).
Configuration
version: '1.0'
commands:
generate:
server_go:
package: petstore
layout: module
module: github.com/acme/petstore
type_mappings:
uuid: github.com/google/uuid.UUID
| Option | Type | Default | Description |
|---|---|---|---|
package |
string | name of the output directory | Name of the Go package; also set by --package-name. |
layout |
package or module |
package |
module also writes go.mod, making the output a module of its own. |
module |
string | example.com/<package> |
Module path written to go.mod. |
main |
boolean | false |
With layout: module, writes cmd/<package>/main.go running a server whose operations answer 501, unless the file exists. |
generate |
list of types, server, strict |
all | Files to write. strict requires server, which requires types. |
embedded_spec |
boolean | true |
Writes openapi.yaml and spec.gen.go embedding it. |
optional_fields |
pointer or omitzero |
pointer |
Optional properties as pointers with omitempty, or as values with omitzero (Go 1.24). |
nullable_type |
tristate or pointer |
tristate |
Optional nullable properties as Nullable[T], or as pointers. |
include_tags |
list of strings | Generates only the operations with one of these tags. | |
exclude_tags |
list of strings | Skips the operations with one of these tags. | |
skip_prune |
boolean | false |
Keeps the component schemas that no generated operation uses. |
validate_requests |
boolean | true |
Validates parameters and request bodies against their schemas. |
validate_responses |
boolean | false |
Validates the bodies of strict responses before writing them (500 when they aren’t valid). |
route_conflicts |
warn or error |
warn |
Serve the patterns http.ServeMux can’t register together through a shared pattern, or report them as errors. |
initialisms |
list of strings | Words written in upper case in identifiers, besides ID, URL, HTTP, JSON and the other initialisms of golint. |
|
type_mappings |
map of strings | Go types of string formats or x-go-type names, e.g. uuid: github.com/google/uuid.UUID. |
|
max_body_bytes |
integer | 0 (no limit) |
Largest request body the strict server reads (413 beyond). |
max_multipart_memory |
integer | 33554432 |
Memory multipart bodies may take before their files are stored on disk. |
action_naming |
list of id, extension, url |
id, extension, url |
Where operation names come from, in order of preference. |