apigenie-generatorOpenAPI clientsclient go
client go
Generate a Go client for the net/http package of Go 1.22 from an OpenAPI document.
From an AsyncAPI document, the command generates a Go Kafka client package instead; see apigenie-generator client go (AsyncAPI).
Usage
apigenie-generator client go [...OPTIONS] INPUT_FILE
Description
The generator writes a Go package whose code uses the standard library only: its go.mod has no
requirements. It shares the types, validation and parameter codecs with
apigenie-generator server go, so a client and a server
generated from the same document read and write values the same way.
| File | Contents |
|---|---|
types.gen.go |
the types of the component schemas the operations use, and of their inline schemas, with Validate() methods |
client.gen.go |
DefaultBaseURL, Servers, SecuritySchemes, Operations, NewClient, an option per security scheme, and per operation its parameters, bodies, response type and methods |
runtime_*.gen.go |
the Client, requests and errors, parameter encoding, streams, multipart bodies, validation, Nullable[T], Date |
go.mod |
with layout: module |
client, err := api.NewClient(
api.WithBaseURL("https://api.example.com/v1"), // DefaultBaseURL otherwise
api.WithAPIKey(os.Getenv("API_KEY")),
api.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
)
if err != nil {
return err
}
res, err := client.GetPet(ctx, 42, nil)
var apiErr *api.APIError
switch {
case errors.As(err, &apiErr):
log.Printf("status %d: %v", apiErr.StatusCode, apiErr.Problem) // RFC 9457 problem details
case err != nil:
return err // transport, encoding or decoding error
default:
fmt.Println(res.JSON200.Name)
}
Methods
Every operation is a method of Client, named after its operationId, whose first argument is a
context.Context, followed by the path parameters, a pointer to a struct with the query, header
and cookie parameters (nil when none is set), the body, and request editors changing the
request before it is sent:
func (c *Client) CreatePet(ctx context.Context, params *CreatePetParams, body NewPet, reqEditors ...RequestEditorFn) (*CreatePetResponse, error)
func (c *Client) CreatePetWithBody(ctx context.Context, params *CreatePetParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreatePetResponse, error)
- An operation with several request media types gets a method per media type
(
UpdatePetWithApplicationMergePatchJSONBody; the bare name sendsapplication/json), and always a...WithBodymethod taking the media type and anio.Reader. - JSON bodies are values of their types, validated with
Validate()before they are sent (validate_requests: falseturns that off);text/*bodies are strings, other media typesio.Readervalues, andapplication/jsonlbodies slices of the items of theiritemSchema. application/x-www-form-urlencodedbodies are encoded field by field with the styles of theirencoding(deepObject, delimited arrays, JSON fields).- Parameters are serialized in their style and
explodemode:simple,labelandmatrixpath parameters,form,spaceDelimited,pipeDelimitedanddeepObjectquery parameters,allowReserved, headers and cookies. Parameters described withcontentare sent as JSON. - Methods set the
Acceptheader to the media types of the documented responses. - Operations marked
x-internal: true(on the operation or its path) are left out, unlessinternal_operationsis set.
Responses
A method returns a response struct with one field per documented status and media type, set for
the response received, next to the raw *http.Response:
type GetPetResponse struct {
HTTPResponse *http.Response
Body []byte // the body, when it was read
Headers200 *GetPet200Headers // typed response headers
JSON200 *Pet // 200, application/json
ApplicationPdf200 io.ReadCloser // 200, application/pdf: left open
ApplicationProblemJSON404 *ProblemDetails // 404, application/problem+json
ApplicationProblemJSONDefault *ProblemDetails
}
- The field names join the media type (
JSONforapplication/json,Textfortext/plain,EventStream,JSONL, the media type otherwise) and the status (200,2XX,Default). application/problem+jsoncontents are*ProblemDetails(type, title, status, detail, instance and the other members inExtensions), whatever their schema.- Binary contents and streams are left open: close the field, or the response with
Close(). Other bodies are read, kept inBody, and closed. - For a status of 400 or more, the method returns the response and an
*APIErrorwith the status, the problem details of anapplication/problem+jsonbody, the body and the response.errors.As(err, &problem)also finds the*ProblemDetails. - An undocumented status or media type sets no field:
Bodyholds the body. - Response headers that can’t be parsed are left unset; their text stays in
HTTPResponse.Header.
Streams
text/event-stream and application/jsonl contents are iterators over their items, typed by the
itemSchema of the media type (OpenAPI 3.2; x-itemSchema in 3.0 and 3.1 documents):
res, err := client.GetTrackingEvents(ctx, id, nil)
if err != nil {
return err
}
defer res.Close()
if events := res.EventStream200; events != nil {
for events.Next() {
event := events.Item() // the itemSchema type, filled from id, event, data and retry
fmt.Println(event.Event, event.Data)
}
if err := events.Err(); err != nil {
return err
}
}
JSONLStream[T]reads one JSON value per line.EventStream[T]follows the server-sent events parsing rules of the HTML standard (datalines joined, comments,id,retry);Event()returns the event as received andLastEventID()the ID to resume from withLast-Event-ID.- Without
itemSchema, server-sent events areServerSentEventvalues and JSON Lines itemsjson.RawMessagevalues. - Go 1.22 has no range-over-func iterators, hence
Next(),Item()andErr().
Multipart bodies
multipart/form-data bodies of object schemas are structs with a field per part:
- Binary parts (
format: binary, orcontentMediaTypein 3.1 and 3.2) areFilevalues (a name, a media type, a reader and extra part headers), arrays of them[]File. A file part is sent with thecontentTypeof its encoding, or itscontentMediaType, unlessFile.ContentTypeis set. Headers the encoding declares are set throughFile.Header. - Object parts, and parts whose encoding has a JSON
contentType, are sent as JSON; other parts as text, a part per item of arrays.
The body is built in memory and sent with its boundary.
Servers
DefaultBaseURL is the first server of the document with an absolute URL, the default values of
its variables applied; WithBaseURL sets another one, and is required when there is none.
Operations with servers of their own (on the operation or its path) are sent there, a relative
server URL being resolved against the base URL; WithOperationServers(false) sends every request
to the base URL instead, e.g. to a test server or a proxy.
Security
Every security scheme of the document gets an option setting its credentials, named With
followed by the name of the scheme:
| Scheme (name in the document) | Option |
|---|---|
apiKey in a header, the query or a cookie (apiKey) |
WithAPIKey(key string) |
http bearer, oauth2, openIdConnect (oauth2) |
WithOauth2(token string), sent as a bearer token |
http basic (basicAuth) |
WithBasicAuth(username, password string) |
A request gets the credentials of the first alternative of its operation’s security
requirements whose schemes all have credentials, so an API key in the query is only sent to the
operations that accept it; an operation with security: [] gets none. WithSecurity(scheme, editor) sets the credentials of any scheme with a RequestEditorFn; obtaining and refreshing
OAuth2 tokens is up to the caller. mutualTLS needs a client certificate in the transport of
the http.Client (WithHTTPClient).
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. - Enums are defined types with constants named after the type and the value
(
PetStatusAvailable). 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.allOfschemas are merged into one struct; ananyOforoneOfwhose members only list required properties (anyOf: [{required: [email]}, {required: [phone]}]) is checked byValidate().date-timestrings aretime.Time,datestringsDate,byteandbinarystrings[]byte.
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 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-internal |
true on an operation or its path item leaves the operation out, unless internal_operations is set |
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 |
x-itemSchema |
itemSchema of a media type in OpenAPI 3.0 and 3.1 documents: the type of the items of a streamed response |
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 client go openapi.yaml --overlay go.overlay.yaml -o out
Limitations
- Callbacks, webhooks and links aren’t generated: they describe requests the server makes or documentation.
Validate()doesn’t checkprefixItems,patternProperties,if/then/else,dependentRequired,dependentSchemasandunevaluatedProperties; patterns using lookaround or backreferences aren’t checked either.- Multipart bodies are built in memory; there are no retries or rate limiting beyond what the
http.Clientdoes. - Exported names of the runtime (
Client,File,Server,Operation,ProblemDetails,Date,Nullable, …) are reserved: schemas with these names get numbered types, e.g.File2. - 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.client_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:
client_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. |
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. |
internal_operations |
boolean | false |
Also generates the operations marked x-internal: true. |
validate_requests |
boolean | true |
Validates request bodies against their schemas before sending them. |
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. |
|
action_naming |
list of id, extension, url |
id, extension, url |
Where method names come from, in order of preference. |