# client go

Source: https://apigenie.pl/techdocs/reference/cli-generate_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)](/techdocs/reference/cli-generate_client_go_asyncapi).

## Usage

```sh
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`](/techdocs/reference/cli-generate_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` |

```go
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:

```go
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 sends `application/json`), and
  always a `...WithBody` method taking the media type and an `io.Reader`.
- JSON bodies are values of their types, validated with `Validate()` before they are sent
  (`validate_requests: false` turns that off); `text/*` bodies are strings, other media types
  `io.Reader` values, and `application/jsonl` bodies slices of the items of their `itemSchema`.
- `application/x-www-form-urlencoded` bodies are encoded field by field with the styles of their
  `encoding` (`deepObject`, delimited arrays, JSON fields).
- Parameters are serialized in their style and `explode` mode: `simple`, `label` and `matrix`
  path parameters, `form`, `spaceDelimited`, `pipeDelimited` and `deepObject` query parameters,
  `allowReserved`, headers and cookies. Parameters described with `content` are sent as JSON.
- Methods set the `Accept` header to the media types of the documented responses.
- Operations marked `x-internal: true` (on the operation or its path) are left out, unless
  `internal_operations` is 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`:

```go
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 (`JSON` for `application/json`, `Text` for `text/plain`,
  `EventStream`, `JSONL`, the media type otherwise) and the status (`200`, `2XX`, `Default`).
- `application/problem+json` contents are `*ProblemDetails` (type, title, status, detail,
  instance and the other members in `Extensions`), whatever their schema.
- Binary contents and streams are left open: close the field, or the response with `Close()`.
  Other bodies are read, kept in `Body`, and closed.
- For a status of 400 or more, the method returns the response and an `*APIError` with the status,
  the problem details of an `application/problem+json` body, the body and the response.
  `errors.As(err, &problem)` also finds the `*ProblemDetails`.
- An undocumented status or media type sets no field: `Body` holds 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):

```go
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 (`data` lines joined, comments, `id`, `retry`); `Event()`
  returns the event as received and `LastEventID()` the ID to resume from with `Last-Event-ID`.
- Without `itemSchema`, server-sent events are `ServerSentEvent` values and JSON Lines items
  `json.RawMessage` values.
- Go 1.22 has no range-over-func iterators, hence `Next()`, `Item()` and `Err()`.

### Multipart bodies

`multipart/form-data` bodies of object schemas are structs with a field per part:

- Binary parts (`format: binary`, or `contentMediaType` in 3.1 and 3.2) are `File` values (a
  name, a media type, a reader and extra part headers), arrays of them `[]File`. A file part is
  sent with the `contentType` of its encoding, or its `contentMediaType`, unless
  `File.ContentType` is set. Headers the encoding declares are set through `File.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 and `any` stay values.
  `optional_fields: omitzero` uses values with `omitzero` (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: pointer` uses pointers for both.
- Enums are defined types with constants named after the type and the value
  (`PetStatusAvailable`).
- `oneOf` and `anyOf` schemas are structs with one pointer per variant. With a discriminator, the
  value goes to the variant its property selects: through the `mapping`, the name of the schema
  or the value the schema gives the property (`const`); other values go to the `defaultMapping`
  variant (`x-defaultMapping` in 3.0 and 3.1 documents), or are kept in `Raw`. Without a
  discriminator, the value goes to the first variant it decodes into.
- `allOf` schemas are merged into one struct; an `anyOf` or `oneOf` whose members only list
  required properties (`anyOf: [{required: [email]}, {required: [phone]}]`) is checked by
  `Validate()`.
- `date-time` strings are `time.Time`, `date` strings `Date`, `byte` and `binary` strings
  `[]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`:

```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
```

```sh
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 check `prefixItems`, `patternProperties`, `if`/`then`/`else`,
  `dependentRequired`, `dependentSchemas` and `unevaluatedProperties`; 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.Client` does.
- 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 with `apigenie 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

```yaml
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. |
