# server go

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

## Usage

```sh
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](https://github.com/oapi-codegen/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 the `http.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. `NewStrictHandler` turns it into a `ServerInterface`.

```go
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.ServeMux` can't register together (it panics), such as `GET /a/{x}/b` and
  `GET /a/b/{y}`, are served through one pattern generalizing them, which sends each request to
  the most specific operation. `route_conflicts: error` reports them as errors instead.

### 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.
- Required properties that are `readOnly` or `writeOnly` are 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()` and `Validate()`.
- `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 without unknown properties
  and validates against.
- `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()`.
- `additionalProperties` are kept in an `AdditionalProperties` map.
- `date-time` strings are `time.Time`, `date` strings `Date`, `byte` and `binary` strings
  `[]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](https://www.rfc-editor.org/rfc/rfc9457) problem details listing the failed checks:

```json
{"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`:

```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 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-internal` isn't honoured: only `x-apigenie` `codegen.disabled` skips operations.
- `text/event-stream` responses are written at once as text, so events can't be streamed;
  `itemSchema` isn't read, so stream items aren't typed (`application/jsonl` bodies are
  `io.Reader` streams).
- `Validate()` doesn't check `prefixItems`, `patternProperties`, `if`/`then`/`else`,
  `dependentRequired`, `dependentSchemas` and `unevaluatedProperties`.
- XML bodies are passed as streams (`io.Reader`), and form or multipart responses too.
- Patterns using lookaround or backreferences, which Go's `regexp` package doesn't support, aren't
  checked (a warning says so). Patterns are compiled when first used.
- `allOf` schemas 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 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.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

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