### Install and verify binary Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Standard binary installation and version check. ```bash $ go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest $ oapi-codegen -version ``` -------------------------------- ### Implementing the ServerInterface Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example implementation of the generated ServerInterface for a PetStore service. ```go type PetStore struct { Pets map[int64]Pet NextId int64 Lock sync.Mutex } // Make sure we conform to ServerInterface var _ ServerInterface = (*PetStore)(nil) func NewPetStore() *PetStore { return &PetStore{ Pets: make(map[int64]Pet), NextId: 1000, } } // FindPets implements all the handlers in the ServerInterface func (p *PetStore) FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams) { p.Lock.Lock() defer p.Lock.Unlock() var result []Pet for _, pet := range p.Pets { if params.Tags != nil { // If we have tags, filter pets by tag for _, t := range *params.Tags { if pet.Tag != nil && (*pet.Tag == t) { result = append(result, pet) } } } else { // Add all pets if we're not filtering result = append(result, pet) } if params.Limit != nil { l := int(*params.Limit) if len(result) >= l { // We're at the limit break } } } w.WriteHeader(http.StatusOK) _ = json.NewEncoder(w).Encode(result) } ``` -------------------------------- ### Install oapi-codegen v2.3.0 or above Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Use this command for current versions under the oapi-codegen organization. ```bash # for the binary install go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest ``` -------------------------------- ### Initial Configuration File for Admin API Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example configuration file that lacks the necessary import-mapping for external references. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json # admin/cfg.yaml package: admin output: server.gen.go generate: models: true chi-server: true output-options: # to make sure that all types are generated skip-prune: true # NOTE that this won't work, as it's missing `import-mapping` ``` -------------------------------- ### Example go.mod diff after pinning Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Shows the change in go.mod when pinning to a specific commit. ```diff diff --git go.mod go.mod index 44f29a4..436a780 100644 --- go.mod +++ go.mod @@ -2,21 +2,20 @@ -require github.com/oapi-codegen/oapi-codegen/v2 v2.1.0 +require github.com/oapi-codegen/oapi-codegen/v2 v2.1.1-0.20240331212514-80f0b978ef16 ``` -------------------------------- ### Install oapi-codegen v2.2.0 or below Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Use this command for older versions of the project under the deepmap organization. ```bash # for the binary install go install github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@v2.2.0 ``` -------------------------------- ### Directory Structure for Multi-Package Setup Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Recommended directory layout for managing multiple OpenAPI specifications in separate packages. ```text ├── admin │ ├── cfg.yaml │ └── generate.go └── common ├── cfg.yaml └── generate.go ``` -------------------------------- ### Generated Client Structure Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example of the generated Go code structure including client structs and interfaces. ```go package client // ... // ClientType defines model for ClientType. type ClientType struct { Name string `json:"name"` } // ... // Client which conforms to the OpenAPI3 specification for this service. type Client struct { // The endpoint of the server conforming to this interface, with scheme, // https://api.deepmap.com for example. This can contain a path relative // to the server, such as https://api.deepmap.com/dev-test, and all the // paths in the swagger spec will be appended to the server. Server string // Doer for performing requests, typically a *http.Client with any // customized settings, such as certificate chains. Client HttpRequestDoer // A list of callbacks for modifying requests which are generated before sending over // the network. RequestEditors []RequestEditorFn } // ... // The interface specification for the client above. type ClientInterface interface { // GetClient request GetClient(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) // UpdateClient request UpdateClient(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) } // ... // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { // GetClientWithResponse request GetClientWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetClientResponse, error) // UpdateClientWithResponse request UpdateClientWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*UpdateClientResponse, error) } type GetClientResponse struct { Body []byte HTTPResponse *http.Response JSON200 *ClientType } // ... ``` -------------------------------- ### Implement client-side authentication Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example of using a security provider with a generated client's request editor function to handle authentication. ```go import ( "context" "fmt" "log" "github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider" ) func main() { basicAuth, err := securityprovider.NewSecurityProviderBasicAuth("my_user", "my_pass") if err != nil { log.Fatal(err) } client, err := NewClient("https://....", WithRequestEditorFn(basicAuth.Intercept)) if err != nil { log.Fatal(err) } resp, err := client.GetClient(context.TODO()) if err != nil { log.Fatal(err) } fmt.Printf("resp.StatusCode: %v\n", resp.StatusCode) } ``` -------------------------------- ### Strict Server Configuration Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example configuration for enabling strict server generation in a YAML configuration file. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json package: api generate: # NOTE another server must be added! chi-server: true strict-server: true output: server.gen.go ``` -------------------------------- ### Define Server URLs in OpenAPI Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example of an OpenAPI specification defining servers with templated variables. ```yaml servers: - url: https://development.gigantic-server.com/v1 description: Development server - url: https://{username}.gigantic-server.com:{port}/{basePath} description: The production API server variables: username: # note! no enum here means it is an open value default: demo description: this value is assigned by the service provider, in this example `gigantic-server.com` port: enum: - '8443' - '443' default: '8443' basePath: # open meaning there is the opportunity to use special base paths as assigned by the provider, default is `v2` default: v2 ``` -------------------------------- ### Generated Go Boilerplate for Server URLs Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example of the Go code generated from the server URL configuration, including constants and helper functions. ```go // (the below does not include comments that are generated) const ServerUrlDevelopmentServer = "https://development.gigantic-server.com/v1" type ServerUrlTheProductionAPIServerBasePathVariable string const ServerUrlTheProductionAPIServerBasePathVariableDefault = "v2" type ServerUrlTheProductionAPIServerPortVariable string const ServerUrlTheProductionAPIServerPortVariable8443 ServerUrlTheProductionAPIServerPortVariable = "8443" const ServerUrlTheProductionAPIServerPortVariable443 ServerUrlTheProductionAPIServerPortVariable = "443" const ServerUrlTheProductionAPIServerPortVariableDefault ServerUrlTheProductionAPIServerPortVariable = ServerUrlTheProductionAPIServerPortVariable8443 type ServerUrlTheProductionAPIServerUsernameVariable string const ServerUrlTheProductionAPIServerUsernameVariableDefault = "demo" func ServerUrlTheProductionAPIServer(basePath ServerUrlTheProductionAPIServerBasePathVariable, port ServerUrlTheProductionAPIServerPortVariable, username ServerUrlTheProductionAPIServerUsernameVariable) (string, error) { // ... } ``` -------------------------------- ### Generated Go Model and Interface Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example of a generated Go struct and client interface based on an OpenAPI specification. ```go // Pet defines model for Pet. type Pet struct { // Name The name of the pet. Name string `json:"name"` // Uuid The pet uuid. Uuid string `json:"uuid"` } // The interface specification for the client above. type ClientInterface interface { // GetHttpPet request GetHttpPet(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*http.Response, error) } ``` -------------------------------- ### OpenAPI Specification for Model Generation Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 An example api.yaml file demonstrating how schemas are referenced and how anonymous objects are handled. ```yaml openapi: "3.0.0" info: version: 1.0.0 title: Generate models paths: /client: get: operationId: getClient responses: 200: content: application/json: schema: # NOTE that Client is generated here, because it's within #/components/schemas $ref: "#/components/schemas/Client" put: operationId: updateClient responses: 400: content: application/json: # NOTE that this anonymous object is /not/ generated because it's an anonymous, but would be generated if using `generate: client` # See https://github.com/oapi-codegen/oapi-codegen/v2/issues/1512 schema: type: object properties: code: type: string required: - code components: schemas: Client: type: object required: - name properties: name: type: string # NOTE that this is not generated by default because it's not referenced. If you want it, you need to use the following YAML configuration: # # output-options: # skip-prune: true Unreferenced: type: object required: - id properties: id: type: integer ``` -------------------------------- ### Implement StrictServerInterface for PetStore Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example implementation of the FindPets handler using the StrictServerInterface, demonstrating how to handle request parameters and return JSON responses. ```go // Make sure we conform to StrictServerInterface var _ StrictServerInterface = (*PetStore)(nil) func NewPetStore() *PetStore { return &PetStore{ Pets: make(map[int64]Pet), NextId: 1000, } } // FindPets implements all the handlers in the ServerInterface func (p *PetStore) FindPets(ctx context.Context, request FindPetsRequestObject) (FindPetsResponseObject, error) { p.Lock.Lock() defer p.Lock.Unlock() var result []Pet for _, pet := range p.Pets { if request.Params.Tags != nil { // If we have tags, filter pets by tag for _, t := range *request.Params.Tags { if pet.Tag != nil && (*pet.Tag == t) { result = append(result, pet) } } } else { // Add all pets if we're not filtering result = append(result, pet) } if request.Params.Limit != nil { l := int(*request.Params.Limit) if len(result) >= l { // We're at the limit break } } } return FindPets200JSONResponse(result), nil } ``` -------------------------------- ### Define OpenAPI Specification Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example OpenAPI 3.0.0 specification defining paths and schemas for client generation. ```yaml openapi: "3.0.0" info: version: 1.0.0 title: Generate models paths: /client: get: operationId: getClient responses: 200: content: application/json: schema: $ref: "#/components/schemas/ClientType" put: operationId: updateClient responses: 400: content: application/json: schema: type: object properties: code: type: string required: - code components: schemas: ClientType: type: object required: - name properties: name: type: string # NOTE that this is not generated by default because it's not referenced. If you want it, you need to use the following YAML configuration: # # output-options: # skip-prune: true Unreferenced: type: object required: - id properties: id: type: integer ``` -------------------------------- ### Invoke oapi-codegen binary via go:generate Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Use this directive when oapi-codegen is installed as a system binary. ```go //go:generate oapi-codegen --config=config.yaml ../../api.yaml ``` -------------------------------- ### Utilize Generated Client Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example usage of the generated client to perform requests with raw responses or parsed response bodies. ```go package client_test import ( "context" "fmt" "log" "net/http" "github.com/oapi-codegen/oapi-codegen/v2/examples/client" ) func TestClient_canCall() { // custom HTTP client hc := http.Client{} // with a raw http.Response { c, err := client.NewClient("http://localhost:1234", client.WithHTTPClient(&hc)) if err != nil { log.Fatal(err) } resp, err := c.GetClient(context.TODO()) if err != nil { log.Fatal(err) } if resp.StatusCode != http.StatusOK { log.Fatalf("Expected HTTP 200 but received %d", resp.StatusCode) } } // or to get a struct with the parsed response body { c, err := client.NewClientWithResponses("http://localhost:1234", client.WithHTTPClient(&hc)) if err != nil { log.Fatal(err) } resp, err := c.GetClientWithResponse(context.TODO()) if err != nil { log.Fatal(err) } if resp.StatusCode() != http.StatusOK { log.Fatalf("Expected HTTP 200 but received %d", resp.StatusCode()) } fmt.Printf("resp.JSON200: %v\n", resp.JSON200) } } ``` -------------------------------- ### Define OpenAPI schema with additionalProperties Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example of an OpenAPI schema definition using additionalProperties as an object. ```yaml components: schemas: Thing: type: object required: - id properties: id: type: integer # object additionalProperties: type: object properties: foo: type: string ``` -------------------------------- ### Complex Schema OpenAPI Specification Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 An example demonstrating the use of anyOf, allOf, and oneOf in an OpenAPI specification. ```yaml openapi: "3.0.0" info: version: 1.0.0 title: Using complex schemas description: An example of `anyOf`, `allOf` and `oneOf` components: schemas: # base types Client: type: object required: - name properties: name: type: string Identity: type: object required: - issuer properties: issuer: type: string # allOf performs a union of all types defined ClientWithId: allOf: - $ref: '#/components/schemas/Client' - properties: id: type: integer required: - id ``` -------------------------------- ### Define an external reference in OpenAPI Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example of using a $ref to point to a schema in an external OpenAPI document. ```yaml responses: 200: description: Success content: application/json: schema: $ref: '#/components/schemas/User' ``` -------------------------------- ### OpenAPI spec for name normalizer example Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 An OpenAPI specification used to demonstrate default camel-case type name generation. ```yaml openapi: "3.0.0" info: version: 1.0.0 title: Example code for the `name-normalizer` output option paths: /api/pets/{petId}: get: summary: Get pet given identifier. operationId: getHttpPet parameters: - name: petId in: path required: true schema: type: string responses: '200': description: valid pet content: application/json: schema: $ref: '#/components/schemas/Pet' components: schemas: Pet: type: object required: - uuid - name properties: uuid: type: string description: The pet uuid. name: type: string description: The name of the pet. Error: required: - code - message properties: code: type: integer format: int32 description: Error code message: type: string description: Error message OneOf2things: description: "Notice that the `things` is not capitalised" oneOf: - type: object required: - id properties: id: type: integer - type: object required: - id properties: id: type: string format: uuid ``` -------------------------------- ### Create NewSecurityProviderApiKey Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider Constructor for creating a new API Key security provider. ```go func NewSecurityProviderApiKey(in, name, apiKey string) (*SecurityProviderApiKey, error) ``` -------------------------------- ### Load Swagger Overlay Options Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/util Configuration options for loading Swagger with an overlay. ```go type LoadSwaggerWithOverlayOpts struct { Path string Strict bool } ``` -------------------------------- ### Create NewSecurityProviderBasicAuth Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider Constructor for creating a new Basic Auth security provider. ```go func NewSecurityProviderBasicAuth(username, password string) (*SecurityProviderBasicAuth, error) ``` -------------------------------- ### Configure oapi-codegen Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Configuration file for enabling client generation. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json package: client output: client.gen.go generate: models: true client: true ``` -------------------------------- ### Define an OpenAPI specification with internal endpoints Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Example OpenAPI specification containing an endpoint marked with x-internal that should be excluded from generation. ```yaml openapi: "3.0.0" info: version: 1.0.0 title: "Example to indicate how to use the OpenAPI Overlay specification (https://github.com/OAI/Overlay-Specification)" paths: /ping: get: responses: '200': description: pet response content: application/json: schema: $ref: '#/components/schemas/Pong' delete: x-internal: true responses: '202': content: {} ``` -------------------------------- ### Manage oapi-codegen as a Go tool Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Recommended approach for managing the dependency within your project's go.mod file. ```bash $ go get -tool github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest # this will then modify your `go.mod` ``` -------------------------------- ### Standard Server Interface and Handler Generation Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Generated code for the ServerInterface and the wrapper that handles parameter binding and middleware execution. ```go // generated code type ServerInterface interface { // ... // Returns all pets // (GET /pets) FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams) // ... } // FindPets operation middleware func (siw *ServerInterfaceWrapper) FindPets(w http.ResponseWriter, r *http.Request) { var err error // Parameter object where we will unmarshal all parameters from the context var params FindPetsParams // ------------- Optional query parameter "tags" ------------- err = runtime.BindQueryParameter("form", true, false, "tags", r.URL.Query(), ¶ms.Tags) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "tags", Err: err}) return } // ------------- Optional query parameter "limit" ------------- err = runtime.BindQueryParameter("form", true, false, "limit", r.URL.Query(), ¶ms.Limit) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "limit", Err: err}) return } handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.FindPets(w, r, params) })) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } handler.ServeHTTP(w, r) } // HandlerWithOptions creates http.Handler with additional options func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.Handler { m := options.BaseRouter if m == nil { m = http.NewServeMux() } if options.ErrorHandlerFunc == nil { options.ErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { http.Error(w, err.Error(), http.StatusBadRequest) } } wrapper := ServerInterfaceWrapper{ Handler: si, HandlerMiddlewares: options.Middlewares, ErrorHandlerFunc: options.ErrorHandlerFunc, } m.HandleFunc("GET "+options.BaseURL+"/pets", wrapper.FindPets) return m } ``` -------------------------------- ### Configure an OpenAPI Overlay file Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Overlay configuration using JSON Path to remove internal endpoints and update metadata. ```yaml overlay: 1.0.0 info: title: Overlay version: 0.0.0 actions: - target: "$" description: Perform a structural overlay, which can be more readable, as it's clear what the shape of the document is update: info: x-overlay-applied: structured-overlay paths: /ping: get: responses: '200': description: Perform a ping request - target: $.paths.*[?(@.x-internal)] description: Remove internal endpoints (noted by x-internal) remove: true - target: $.paths.*.*[?(@.x-internal)] description: Remove internal endpoints (noted by x-internal) remove: true ``` -------------------------------- ### OpenAPI Schema with Potential Naming Clashes Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 An example OpenAPI definition where component schemas named with 'Request' or 'Response' suffixes conflict with generated client code. ```yaml openapi: "3.0.0" info: version: 1.0.0 title: "Show that generated client boilerplate can clash if schemas are well named i.e. `*Request` and `*Response`" paths: /client: put: operationId: updateClient requestBodies: application/json: schema: $ref: '#/components/schemas/UpdateClientRequest' responses: 400: content: application/json: schema: $ref: '#/components/schemas/UpdateClientResponse' components: schemas: UpdateClientRequest: type: object properties: code: type: string required: - code UpdateClientResponse: type: object required: - name properties: name: type: string ``` -------------------------------- ### Create NewSecurityProviderBearerToken Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider Constructor for creating a new Bearer Token security provider. ```go func NewSecurityProviderBearerToken(token string) (*SecurityProviderBearerToken, error) ``` -------------------------------- ### Load Swagger with Overlay Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/util Loads a Swagger specification with specific overlay options. ```go func LoadSwaggerWithOverlay(filePath string, opts LoadSwaggerWithOverlayOpts) (swagger *openapi3.T, err error) ``` -------------------------------- ### Strict Server Function Signature Comparison Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Shows the difference in function signatures between standard and strict server implementations. ```diff -FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams) +FindPets(ctx context.Context, request FindPetsRequestObject) (FindPetsResponseObject, error) ``` -------------------------------- ### Configure local template paths Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Specify relative or absolute paths to custom template files in the configuration file. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json # ... output-options: user-templates: client-with-responses.tmpl: ./custom-template.tmpl additional-properties.tmpl: /tmp/foo.bar typedef.tmpl: no-prefix.tmpl ``` -------------------------------- ### Implement allOf Schema Composition Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Generated Go structs demonstrating how allOf merges fields, with later definitions overriding earlier ones. ```go // ClientWithId defines model for ClientWithId. type ClientWithId struct { Id int `json:"id"` Name string `json:"name"` } // IdentityWithDuplicateField defines model for IdentityWithDuplicateField. type IdentityWithDuplicateField struct { Issuer struct { Name string `json:"name"` } `json:"issuer"` } ``` -------------------------------- ### Load Swagger Specification Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/util Loads an OpenAPI specification from a file path. ```go func LoadSwagger(filePath string) (swagger *openapi3.T, err error) ``` -------------------------------- ### Implement ClientOrIdentity union methods Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Methods for managing union data within a ClientOrIdentity struct using JSON marshaling and merging. ```go // FromIdentity overwrites any union data inside the ClientOrIdentity as the provided Identity func (t *ClientOrIdentity) FromIdentity(v Identity) error { b, err := json.Marshal(v) t.union = b return err } // MergeIdentity performs a merge with any union data inside the ClientOrIdentity, using the provided Identity func (t *ClientOrIdentity) MergeIdentity(v Identity) error { b, err := json.Marshal(v) if err != nil { return err } merged, err := runtime.JSONMerge(t.union, b) t.union = merged return err } func (t ClientOrIdentity) MarshalJSON() ([]byte, error) { b, err := t.union.MarshalJSON() return b, err } func (t *ClientOrIdentity) UnmarshalJSON(b []byte) error { err := t.union.UnmarshalJSON(b) return err } ``` -------------------------------- ### Go Build Failure Output Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Error messages resulting from redeclared types and missing fields in the generated client code. ```text # github.com/oapi-codegen/oapi-codegen/v2/examples/clienttypenameclash ./client.gen.go:184:6: UpdateClientResponse redeclared in this block ./client.gen.go:17:6: other declaration of UpdateClientResponse ./client.gen.go:192:7: r.HTTPResponse undefined (type UpdateClientResponse has no field or method HTTPResponse) ./client.gen.go:193:12: r.HTTPResponse undefined (type UpdateClientResponse has no field or method HTTPResponse) ./client.gen.go:200:7: r.HTTPResponse undefined (type UpdateClientResponse has no field or method HTTPResponse) ./client.gen.go:201:12: r.HTTPResponse undefined (type UpdateClientResponse has no field or method HTTPResponse) ./client.gen.go:224:3: unknown field Body in struct literal of type UpdateClientResponse ./client.gen.go:225:3: unknown field HTTPResponse in struct literal of type UpdateClientResponse ./client.gen.go:234:12: response.JSON400 undefined (type *UpdateClientResponse has no field or method JSON400) ``` -------------------------------- ### Corrected Configuration with Import Mapping Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Configuration file updated with import-mapping to resolve external references to the correct Go package. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json package: admin output: server.gen.go generate: models: true chi-server: true output-options: # to make sure that all types are generated skip-prune: true import-mapping: # for a given file/URL that is $ref'd, point `oapi-codegen` to the Go package that this spec is generated into, to perform Go package imports ../common/api.yaml: github.com/oapi-codegen/oapi-codegen/v2/examples/import-mapping/common ``` -------------------------------- ### Implement Error Interface Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider Implements the error interface for SecurityProviderError. ```go func (e SecurityProviderError) Error() string ``` -------------------------------- ### Parse Command Line List Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/util Parses a comma-separated string list from command line input, trimming whitespace from results. ```go func ParseCommandLineList(input string) []string ``` -------------------------------- ### Configure oapi-codegen with an overlay Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Configuration file for oapi-codegen specifying the path to the overlay file. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json package: api output: ping.gen.go generate: models: true gorilla-server: true embedded-spec: true output-options: overlay: path: overlay.yaml ``` -------------------------------- ### Enable nullable-type in configuration Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Configuration setting to enable the use of the nullable.Nullable type. ```yaml output-options: nullable-type: true ``` -------------------------------- ### oapi-codegen Configuration for Models Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Configuration files to enable model generation and handle unreferenced schemas. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json package: onlymodels output: only-models.gen.go generate: models: true ``` ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json package: onlymodels output: only-models.gen.go generate: models: true output-options: # NOTE that this is only required for the `Unreferenced` type skip-prune: true ``` -------------------------------- ### Define inline templates Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Provide template content directly within the configuration file using the pipe operator for multi-line strings. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json # ... output-options: user-templates: # NOTE the use of the `|` (pipe symbol) here to denote that this is a # multi-line statement that should preserve newlines. More reading: # https://stackoverflow.com/a/18708156/2257038 and # https://stackoverflow.com/a/15365296/2257038 client-with-responses.tmpl: | // ClientWithResponses builds on ClientInterface to offer response payloads type ClientWithResponses struct { ClientInterface } ... ``` -------------------------------- ### Execute oapi-codegen for multiple specs Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Commands to generate code from multiple OpenAPI specification files using specific configuration files. ```bash $ go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg-api.yaml ../admin/api.yaml $ go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg-user.yaml ../common/api.yaml ``` -------------------------------- ### Define Base Go Models Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Standard Go struct definitions for base OpenAPI schemas. ```go // Client defines model for Client. type Client struct { Name string `json:"name"` } // Identity defines model for Identity. type Identity struct { Issuer string `json:"issuer"` } ``` -------------------------------- ### Configure oapi-codegen for Server URLs Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Configuration file to enable server URL generation in the output code. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json package: serverurls output: gen.go generate: # NOTE that this uses default settings - if you want to use initialisms to generate i.e. `ServerURLDevelopmentServer`, you should look up the `output-options.name-normalizer` configuration server-urls: true ``` -------------------------------- ### NewSecurityProviderBasicAuth Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider Creates a new provider for Basic Authentication. ```APIDOC ## func NewSecurityProviderBasicAuth(username, password string) (*SecurityProviderBasicAuth, error) ### Description Creates a new SecurityProviderBasicAuth instance that encodes the provided username and password for use in an Authorization header. ### Parameters - **username** (string) - Required - The username for authentication. - **password** (string) - Required - The password for authentication. ``` -------------------------------- ### Configure YAML with JSON Schema Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Include the schema comment in your YAML configuration file for IDE support. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json package: api # ... ``` -------------------------------- ### Strict Server Interface Implementation Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Generated code for the StrictServerInterface, which further reduces boilerplate by abstracting request/response handling. ```go // StrictServerInterface represents all server handlers. type StrictServerInterface interface { // ... // Returns all pets // (GET /pets) FindPets(ctx context.Context, request FindPetsRequestObject) (FindPetsResponseObject, error) // ... } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } // FindPets operation middleware func (sh *strictHandler) FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams) { var request FindPetsRequestObject request.Params = params handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.FindPets(ctx, request.(FindPetsRequestObject)) } for _, middleware := range sh.middlewares { handler = middleware(handler, "FindPets") } response, err := handler(r.Context(), w, r, request) if err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) } else if validResponse, ok := response.(FindPetsResponseObject); ok { if err := validResponse.VisitFindPetsResponse(w); err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) } } ``` -------------------------------- ### Load ECDSA Private Key Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/ecdsafile Reads an ECDSA private key from an X509 encoding stored in a PEM encoding. ```go func LoadEcdsaPrivateKey(buf []byte) (*ecdsa.PrivateKey, error) ``` -------------------------------- ### NewSecurityProviderApiKey Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider Creates a new provider to attach an API key to a request via cookie, header, or query parameter. ```APIDOC ## func NewSecurityProviderApiKey(in, name, apiKey string) (*SecurityProviderApiKey, error) ### Description Creates a new SecurityProviderApiKey instance. The 'in' parameter specifies the location (cookie, header, or query), 'name' is the key name, and 'apiKey' is the value. ### Parameters - **in** (string) - Required - The location to attach the key (cookie, header, or query). - **name** (string) - Required - The name of the key. - **apiKey** (string) - Required - The API key value. ``` -------------------------------- ### Intercept Request with Basic Auth Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider Attaches a base64-encoded Authorization header to the request. ```go func (s *SecurityProviderBasicAuth) Intercept(ctx context.Context, req *http.Request) error ``` -------------------------------- ### Resulting Type Renaming Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Comparison showing how the generated type name changes after applying the suffix configuration. ```diff -type UpdateClientResponse struct { +type UpdateClientResp struct { Body []byte HTTPResponse *http.Response JSON400 *UpdateClientResponse } ``` -------------------------------- ### Generate Code via Go Generate Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Using the go:generate directive to trigger the code generation process. ```go package client //go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml ``` -------------------------------- ### Configure HTTPS template paths Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Reference remote templates using HTTPS URLs. Using specific tags or commit hashes is recommended over branches for reproducibility. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json # ... output-options: user-templates: # The following are referencing a version of the default client-with-responses.tmpl file, but loaded in through GitHub's raw.githubusercontent.com. The general form to use raw.githubusercontent.com is as follows https://raw.githubusercontent.com////path/to/template/template.tmpl # Alternatively using raw.githubusercontent.com with a hash client-with-responses.tmpl: https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/ad5eada4f3ccc28a88477cef62ea21c17fc8aa01/pkg/codegen/templates/client-with-responses.tmpl # Alternatively using raw.githubusercontent.com with a tag client-with-responses.tmpl: https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.1.0/pkg/codegen/templates/client-with-responses.tmpl # Alternatively using raw.githubusercontent.com with a branch client-with-responses.tmpl: https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/master/pkg/codegen/templates/client-with-responses.tmpl ``` -------------------------------- ### Error Message for Missing Import Mapping Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 The error output generated when external references are not mapped to a Go package. ```text error generating code: error creating operation definitions: error generating response definitions: error generating request body definition: error turning reference (../common/api.yaml#/components/schemas/User) into a Go type: unrecognized external reference '../common/api.yaml'; please provide the known import for this reference using option --import-mapping ``` -------------------------------- ### Enable deprecated auth scopes on context Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Configuration snippet to re-enable legacy auth scope context keys for existing middleware compatibility. ```yaml compatibility: enable-auth-scopes-on-context: true ``` -------------------------------- ### Configure oapi-codegen for User API Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Configuration file for the User API component. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json package: samepackage output: user.gen.go generate: models: true output-options: # to make sure that all types are generated skip-prune: true ``` -------------------------------- ### Load ECDSA Public Key Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/ecdsafile Reads an ECDSA public key from an X509 encoding stored in a PEM encoding. ```go func LoadEcdsaPublicKey(buf []byte) (*ecdsa.PublicKey, error) ``` -------------------------------- ### Define SecurityProviderApiKey Error Constant Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider Defines the error constant for invalid 'in' parameters in API Key security providers. ```go const ( // ErrSecurityProviderApiKeyInvalidIn indicates a usage of an invalid In. // Should be cookie, header or query ErrSecurityProviderApiKeyInvalidIn = SecurityProviderError("invalid 'in' specified for apiKey") ) ``` -------------------------------- ### Configuring response-type-suffix Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Updated configuration using the response-type-suffix option to avoid naming collisions. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json package: client output: client.gen.go generate: models: true client: true +output-options: + response-type-suffix: Resp ``` -------------------------------- ### Implement anyOf Union Types Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Generated Go code for anyOf schemas, providing methods to access, set, and merge union data. ```go import ( "encoding/json" "github.com/oapi-codegen/runtime" ) // ClientAndMaybeIdentity defines model for ClientAndMaybeIdentity. type ClientAndMaybeIdentity struct { union json.RawMessage } // AsClient returns the union data inside the ClientAndMaybeIdentity as a Client func (t ClientAndMaybeIdentity) AsClient() (Client, error) { var body Client err := json.Unmarshal(t.union, &body) return body, err } // FromClient overwrites any union data inside the ClientAndMaybeIdentity as the provided Client func (t *ClientAndMaybeIdentity) FromClient(v Client) error { b, err := json.Marshal(v) t.union = b return err } // MergeClient performs a merge with any union data inside the ClientAndMaybeIdentity, using the provided Client func (t *ClientAndMaybeIdentity) MergeClient(v Client) error { b, err := json.Marshal(v) if err != nil { return err } merged, err := runtime.JSONMerge(t.union, b) t.union = merged return err } // AsIdentity returns the union data inside the ClientAndMaybeIdentity as a Identity func (t ClientAndMaybeIdentity) AsIdentity() (Identity, error) { var body Identity err := json.Unmarshal(t.union, &body) return body, err } // FromIdentity overwrites any union data inside the ClientAndMaybeIdentity as the provided Identity func (t *ClientAndMaybeIdentity) FromIdentity(v Identity) error { b, err := json.Marshal(v) t.union = b return err } // MergeIdentity performs a merge with any union data inside the ClientAndMaybeIdentity, using the provided Identity func (t *ClientAndMaybeIdentity) MergeIdentity(v Identity) error { b, err := json.Marshal(v) if err != nil { return err } merged, err := runtime.JSONMerge(t.union, b) t.union = merged return err } func (t ClientAndMaybeIdentity) MarshalJSON() ([]byte, error) { b, err := t.union.MarshalJSON() return b, err } func (t *ClientAndMaybeIdentity) UnmarshalJSON(b []byte) error { err := t.union.UnmarshalJSON(b) return err } ``` -------------------------------- ### Generated Go Code with External Reference Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 The resulting Go code showing the generated import and type alias for the external reference. ```go package admin import ( // ... externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/examples/import-mapping/common" ) // User defines model for User. type User = externalRef0.User ``` -------------------------------- ### Generated Go Model Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 The resulting Go code generated from the OpenAPI schema. ```go package onlymodels // Client defines model for Client. type Client struct { Name string `json:"name"` } ``` -------------------------------- ### Generate Go model with explicit additionalProperties: true Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 Use this configuration when the schema allows arbitrary additional properties of any type. ```yaml components: schemas: Thing: type: object required: - id properties: id: type: integer # explicit true additionalProperties: true ``` ```go // Thing defines model for Thing. type Thing struct { Id int `json:"id"` AdditionalProperties map[string]interface{} `json:"-"` } ``` ```go // Getter for additional properties for Thing. Returns the specified // element and whether it was found func (a Thing) Get(fieldName string) (value interface{}, found bool) { if a.AdditionalProperties != nil { value, found = a.AdditionalProperties[fieldName] } return } // Setter for additional properties for Thing func (a *Thing) Set(fieldName string, value interface{}) { if a.AdditionalProperties == nil { a.AdditionalProperties = make(map[string]interface{}) } a.AdditionalProperties[fieldName] = value } // Override default JSON handling for Thing to handle AdditionalProperties func (a *Thing) UnmarshalJSON(b []byte) error { object := make(map[string]json.RawMessage) err := json.Unmarshal(b, &object) if err != nil { return err } if raw, found := object["id"]; found { err = json.Unmarshal(raw, &a.Id) if err != nil { return fmt.Errorf("error reading 'id': %w", err) } delete(object, "id") } if len(object) != 0 { a.AdditionalProperties = make(map[string]interface{}) for fieldName, fieldBuf := range object { var fieldVal interface{} err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err) } a.AdditionalProperties[fieldName] = fieldVal } } return nil } // Override default JSON handling for Thing to handle AdditionalProperties func (a Thing) MarshalJSON() ([]byte, error) { var err error object := make(map[string]json.RawMessage) object["id"], err = json.Marshal(a.Id) if err != nil { return nil, fmt.Errorf("error marshaling 'id': %w", err) } for fieldName, field := range a.AdditionalProperties { object[fieldName], err = json.Marshal(field) if err != nil { return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err) } } return json.Marshal(object) } ``` -------------------------------- ### Configure optional pointer and omitzero behavior Source: https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2 YAML configuration for oapi-codegen to skip optional pointers and apply omitzero tags globally. ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/v2.7.2/configuration-schema.json package: preferskipoptionalpointerwithomitzero output: gen.go generate: # ... output-options: # ... prefer-skip-optional-pointer: true prefer-skip-optional-pointer-with-omitzero: true ```