Documentation
¶
Overview ¶
Package openapi generates OpenAPI 3.1 documents from Go request and response types, translating validate tags into JSON Schema constraints (min:3 on a string becomes minLength, in:a,b becomes enum, required populates the required list). Rules without a JSON Schema counterpart are skipped rather than approximated. A Generator accumulates operations and renders a Document or its JSON; DocsHTML serves a Scalar page for it.
Index ¶
- Variables
- func DocsHTML(title, specURL string) []byte
- type APIKeyLocation
- type Components
- type Document
- type Generator
- type Header
- type Info
- type MediaType
- type NoBody
- type Operation
- type OperationOption
- func Deprecated() OperationOption
- func RequestOptional() OperationOption
- func RequestRequired() OperationOption
- func WithDefaultResponse[Body any](opts ...ResponseOption) OperationOption
- func WithDescription(description string) OperationOption
- func WithOperationID(id string) OperationOption
- func WithParameter(parameter Parameter) OperationOption
- func WithRequestDescription(description string) OperationOption
- func WithRequestExample(value any) OperationOption
- func WithResponse[Body any](status int, opts ...ResponseOption) OperationOption
- func WithSecurity(first SecurityRequirement, alternatives ...SecurityRequirement) OperationOption
- func WithSummary(summary string) OperationOption
- func WithTags(tags ...string) OperationOption
- func WithoutSecurity() OperationOption
- type Option
- func WithDefaultSecurity(first SecurityRequirement, alternatives ...SecurityRequirement) Option
- func WithInfoDescription(description string) Option
- func WithSchema[T any](schema *Schema) Option
- func WithSchemaTransform[T any](transform func(*Schema) error) Option
- func WithSecurityScheme(name string, scheme SecurityScheme) Option
- func WithServer(url, description string) Option
- func WithValidator(v *validator.Validator) Option
- type Parameter
- type PathItem
- type RequestBody
- type Response
- type ResponseOption
- type Schema
- type SecurityRequirement
- type SecurityScheme
- type Server
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalidOption reports nil options or invalid option arguments, including // empty required text, nil schemas or invalid transforms, unsupported authentication, // undefined or empty security requirements, malformed examples, duplicate or // forbidden headers/parameters, and optional explicit path parameters. ErrInvalidOption = errors.New("openapi: invalid option") // ErrInvalidOperation reports an unusable Add call: an unknown method, a // relative path or one with a query or fragment, no response, a duplicate // response code or operation ID, a status outside 100..599, a missing explicit // path placeholder, or body metadata/examples on an operation without content. ErrInvalidOperation = errors.New("openapi: invalid operation") // ErrOperationExists reports an Add for a method and path already // registered. ErrOperationExists = errors.New("openapi: operation already exists") )
Errors returned for invalid generator configuration and operations; they are wrapped, so match them with errors.Is.
Functions ¶
func DocsHTML ¶
DocsHTML returns an HTML page that renders the OpenAPI document served at specURL with Scalar (https://github.com/scalar/scalar), loaded from the jsDelivr CDN. title and specURL are interpolated verbatim, so they must be trusted values, not user input.
Types ¶
type APIKeyLocation ¶ added in v0.3.0
type APIKeyLocation string
APIKeyLocation selects the input carrying an API key.
const ( HeaderLocation APIKeyLocation = "header" QueryLocation APIKeyLocation = "query" CookieLocation APIKeyLocation = "cookie" )
type Components ¶
type Components struct {
Schemas map[string]*Schema `json:"schemas,omitempty"`
SecuritySchemes map[string]*SecurityScheme `json:"securitySchemes,omitempty"`
}
Components holds the named schemas referenced by $ref, one per named struct type reachable from the registered operations.
type Document ¶
type Document struct {
OpenAPI string `json:"openapi"`
Info Info `json:"info"`
Paths map[string]PathItem `json:"paths,omitempty"`
Components *Components `json:"components,omitempty"`
Servers []Server `json:"servers,omitempty"`
Security []SecurityRequirement `json:"security,omitzero"`
}
Document is the generated OpenAPI 3.1 document, the subset of the specification the Generator emits. It marshals with encoding/json.
type Generator ¶
type Generator struct {
// contains filtered or unexported fields
}
Generator accumulates operations and the component schemas they reference. Schema names are allocated on first use and kept stable; distinct types that flatten to the same name get numeric suffixes. It is not safe for concurrent use.
Example (Documentation) ¶
package main
import (
"fmt"
"net/http"
"github.com/libtnb/validator/contrib/openapi"
)
func main() {
type createProduct struct {
Name string `json:"name" validate:"required" openapi:"description=Product name,example=Notebook"`
OldID string `json:"oldId" openapi:"description='Compatibility identifier, use id instead',deprecated"`
}
type product struct {
ID int `json:"id" openapi:"description=Product ID,example=42,readOnly"`
}
g := openapi.MustNew("Catalog", "1.0.0",
openapi.WithSecurityScheme("apiKey", openapi.APIKeyScheme("X-API-Key", openapi.HeaderLocation)),
openapi.WithDefaultSecurity(openapi.SecurityRequirement{"apiKey"}),
)
err := g.Add[createProduct](http.MethodPost, "/products",
openapi.WithOperationID("createProduct"), openapi.WithDescription("Create a product."),
openapi.WithRequestExample(createProduct{Name: "Notebook"}),
openapi.WithResponse[product](http.StatusCreated, openapi.ResponseExample(product{ID: 42})),
)
if err != nil {
panic(err)
}
operation := g.Document().Paths["/products"]["post"]
properties := operation.RequestBody.Content["application/json"].Schema.Properties
fmt.Println(operation.OperationID)
fmt.Println(properties["name"].Description)
fmt.Println(properties["oldId"].Deprecated)
fmt.Println(string(operation.Responses["201"].Content["application/json"].Example))
}
Output: createProduct Product name true {"id":42}
func New ¶
New constructs a Generator for an API with the given title and version. Returns ErrInvalidOption when either is blank or an option fails.
func (*Generator) Add ¶
func (g *Generator) Add[Request any](method, path string, opts ...OperationOption) error
Add registers an operation for method and path. Request describes the input: fields tagged uri become path parameters, fields tagged query become query parameters (required when their rules say so), and for POST, PUT and PATCH the remaining json-visible fields form the request body; use NoBody for none. At least one WithResponse or WithDefaultResponse option is required. Generation is transactional: on error, paths, components and schema-name allocation are unchanged.
Returns ErrInvalidOperation for a bad method, path or response set, ErrOperationExists when the method and path are already registered, ErrInvalidOption for invalid option arguments (including security references), and a wrapped contextual error when a type's validate/openapi tags or schema transform fail. Documentation tags do not constitute generator options.
type Header ¶ added in v0.3.0
type Header struct {
Description string `json:"description,omitempty"`
Required bool `json:"required,omitempty,omitzero"`
Schema *Schema `json:"schema,omitempty"`
Example jsontext.Value `json:"example,omitzero"`
}
Header describes a response header, whose name is the key in Response.Headers.
type Info ¶
type Info struct {
Title string `json:"title"`
Version string `json:"version"`
Description string `json:"description,omitempty"`
}
Info identifies the API by the title and version given to New.
type MediaType ¶
type MediaType struct {
Schema *Schema `json:"schema,omitempty"`
// Nil omits the example; jsontext.Value("null") emits an explicit JSON null.
Example jsontext.Value `json:"example,omitzero"`
}
MediaType associates a content type entry with its schema.
type NoBody ¶ added in v0.2.1
type NoBody struct{}
NoBody is the type argument for an operation without a JSON request body or for a response without content, such as 204.
type Operation ¶
type Operation struct {
OperationID string `json:"operationId,omitempty"`
Description string `json:"description,omitempty"`
Deprecated bool `json:"deprecated,omitempty,omitzero"`
// Nil inherits document security; a non-nil empty slice disables it.
Security []SecurityRequirement `json:"security,omitzero"`
Summary string `json:"summary,omitempty,omitzero"`
Tags []string `json:"tags,omitempty"`
Parameters []*Parameter `json:"parameters,omitempty"`
RequestBody *RequestBody `json:"requestBody,omitempty"`
Responses map[string]*Response `json:"responses"`
}
Operation describes one HTTP operation: its parameters, optional request body and responses keyed by status code or "default".
type OperationOption ¶ added in v0.2.1
type OperationOption func(*operationConfig) error
OperationOption configures one Add call.
func Deprecated ¶ added in v0.3.0
func Deprecated() OperationOption
Deprecated marks an operation as deprecated without removing it.
func RequestOptional ¶ added in v0.3.0
func RequestOptional() OperationOption
RequestOptional allows omitting the generated request body, even when some of its properties are required if a body is supplied.
func RequestRequired ¶ added in v0.3.0
func RequestRequired() OperationOption
RequestRequired marks the generated request body as required without changing property requirements or the server's runtime validation.
func WithDefaultResponse ¶ added in v0.2.1
func WithDefaultResponse[Body any](opts ...ResponseOption) OperationOption
WithDefaultResponse adds the OpenAPI "default" response, used for any status not listed explicitly; Body follows the WithResponse rules.
func WithDescription ¶ added in v0.3.0
func WithDescription(description string) OperationOption
WithDescription sets the operation's description.
func WithOperationID ¶ added in v0.3.0
func WithOperationID(id string) OperationOption
WithOperationID sets a nonblank operation identifier. An ID must be unique within the document; it is not derived from a handler or URL.
func WithParameter ¶ added in v0.3.0
func WithParameter(parameter Parameter) OperationOption
WithParameter adds a typed parameter or replaces the inferred parameter with the same (in, name). Replacement is complete, including its schema and required flag. Path parameters must be required. Repeated explicit parameters are errors.
func WithRequestDescription ¶ added in v0.3.0
func WithRequestDescription(description string) OperationOption
WithRequestDescription describes the JSON request body. It is an error to use this option when the operation has no generated body.
func WithRequestExample ¶ added in v0.3.0
func WithRequestExample(value any) OperationOption
WithRequestExample snapshots a JSON request example, including an explicit nil (JSON null). Invalid JSON values and operations without a body are errors.
func WithResponse ¶ added in v0.2.1
func WithResponse[Body any](status int, opts ...ResponseOption) OperationOption
WithResponse adds a response for an HTTP status whose JSON body is Body; use NoBody for a response without content. A status outside 100..599 or a code declared twice on one operation is ErrInvalidOperation at Add.
func WithSecurity ¶ added in v0.3.0
func WithSecurity(first SecurityRequirement, alternatives ...SecurityRequirement) OperationOption
WithSecurity overrides document authentication for an operation. At least one nonempty requirement is mandatory; use WithoutSecurity for a public operation.
func WithSummary ¶ added in v0.2.1
func WithSummary(summary string) OperationOption
WithSummary sets the operation summary, trimmed of surrounding whitespace.
func WithTags ¶ added in v0.2.1
func WithTags(tags ...string) OperationOption
WithTags appends operation tags, trimmed; a blank tag is ErrInvalidOption.
func WithoutSecurity ¶ added in v0.3.0
func WithoutSecurity() OperationOption
WithoutSecurity explicitly makes an operation public in the document by emitting security: [], overriding any document-wide requirements.
type Option ¶
Option configures a Generator during New; the first error aborts construction.
func WithDefaultSecurity ¶ added in v0.3.0
func WithDefaultSecurity(first SecurityRequirement, alternatives ...SecurityRequirement) Option
WithDefaultSecurity sets document-wide authentication requirements. Each requirement combines schemes with AND; separate requirements are alternatives.
func WithInfoDescription ¶ added in v0.3.0
WithInfoDescription sets the API's overall description.
func WithSchema ¶ added in v0.2.1
WithSchema replaces the schema inferred for T (pointer layers ignored) wherever T appears, for types whose wire format reflection cannot see. The schema is deep-copied. A nil schema or T being NoBody is ErrInvalidOption.
func WithSchemaTransform ¶ added in v0.3.0
WithSchemaTransform changes a named Go type's inferred schema without replacing its generated fields. Built-in and anonymous types are rejected; use WithSchema for scalar wire formats. It runs each time a schema is inferred: once for a named struct component, per operation for a request body, and per occurrence for any inline named type or custom marshaler. It receives the inferred type schema before field-specific rules and tags are added. A struct schema already contains its children's rules and tags. A top-level request is transformed after its body fields have been generated, excluding path/query parameters. WithSchema takes precedence over transforms. The callback must not retain or mutate the schema after returning. Errors abort Add without committing any generated state.
Example ¶
package main
import (
"fmt"
"net/http"
"github.com/libtnb/validator/contrib/openapi"
)
func main() {
type contact struct {
Email string `json:"email" openapi:"description=Email address"`
Phone string `json:"phone" openapi:"description=Phone number"`
}
g := openapi.MustNew("Contacts", "1.0.0", openapi.WithSchemaTransform[contact](func(schema *openapi.Schema) error {
schema.AnyOf = []*openapi.Schema{{Required: []string{"email"}}, {Required: []string{"phone"}}}
return nil
}))
if err := g.Add[contact](http.MethodPost, "/contacts", openapi.RequestRequired(), openapi.WithResponse[openapi.NoBody](204)); err != nil {
panic(err)
}
body := g.Document().Paths["/contacts"]["post"].RequestBody
fmt.Println(body.Required)
fmt.Println(len(body.Content["application/json"].Schema.Properties))
fmt.Println(len(body.Content["application/json"].Schema.AnyOf))
}
Output: true 2 2
func WithSecurityScheme ¶ added in v0.3.0
func WithSecurityScheme(name string, scheme SecurityScheme) Option
WithSecurityScheme registers API key or HTTP authentication by name. Duplicate names and incomplete schemes are errors. Requirement references are checked after New's options have all been applied, so option order does not matter.
func WithServer ¶ added in v0.3.0
WithServer appends an API base URL. Relative URLs are allowed by OpenAPI.
func WithValidator ¶
WithValidator selects the Validator whose tag name, naming function and rule registry are used to inspect validate tags; the default is validator.Default. A nil v is ErrInvalidOption.
type Parameter ¶
type Parameter struct {
Name string `json:"name"`
In string `json:"in"` // "path", "query", "header", or "cookie"
Required bool `json:"required,omitempty,omitzero"`
Schema *Schema `json:"schema,omitempty"`
Description string `json:"description,omitempty"`
Deprecated bool `json:"deprecated,omitempty,omitzero"`
Example jsontext.Value `json:"example,omitzero"`
}
Parameter describes an inferred uri/query input or an explicitly declared path, query, header, or cookie input. Path parameters are always required.
type RequestBody ¶
type RequestBody struct {
Description string `json:"description,omitempty"`
Required bool `json:"required,omitempty,omitzero"`
Content map[string]*MediaType `json:"content"`
}
RequestBody describes a JSON request body; Required is set when any body property is required.
type Response ¶
type Response struct {
Description string `json:"description"`
Content map[string]*MediaType `json:"content,omitempty"`
Headers map[string]*Header `json:"headers,omitempty"`
}
Response describes one HTTP response; Content is nil for NoBody.
type ResponseOption ¶ added in v0.2.1
type ResponseOption func(*responseOptions) error
ResponseOption configures one WithResponse or WithDefaultResponse entry.
func ResponseDescription ¶ added in v0.2.1
func ResponseDescription(description string) ResponseOption
ResponseDescription overrides the response description, which defaults to the HTTP status text ("Created") or "Response" for the default response. A blank description is ErrInvalidOption.
func ResponseExample ¶ added in v0.3.0
func ResponseExample(value any) ResponseOption
ResponseExample snapshots the response's JSON example. Passing nil emits example: null; omitting this option emits no example. NoBody cannot have one.
func ResponseHeader ¶ added in v0.3.0
func ResponseHeader(name string, header Header) ResponseOption
ResponseHeader documents a response header. Names are compared without case; repeated names are errors. Content-Type is described through response content.
type Schema ¶
type Schema struct {
Ref string `json:"$ref,omitempty,omitzero"`
Type string `json:"type,omitempty,omitzero"`
Format string `json:"format,omitempty,omitzero"`
Description string `json:"description,omitempty,omitzero"`
Example jsontext.Value `json:"example,omitzero"`
Default jsontext.Value `json:"default,omitzero"`
Const jsontext.Value `json:"const,omitzero"`
Deprecated bool `json:"deprecated,omitempty,omitzero"`
ReadOnly bool `json:"readOnly,omitempty,omitzero"`
WriteOnly bool `json:"writeOnly,omitempty,omitzero"`
AllOf []*Schema `json:"allOf,omitempty"`
AnyOf []*Schema `json:"anyOf,omitempty"`
OneOf []*Schema `json:"oneOf,omitempty"`
Not *Schema `json:"not,omitempty"`
Properties map[string]*Schema `json:"properties,omitempty"`
Items *Schema `json:"items,omitempty"`
AdditionalProperties *Schema `json:"additionalProperties,omitempty"`
Required []string `json:"required,omitempty"`
Enum []any `json:"enum,omitempty"`
Pattern string `json:"pattern,omitempty,omitzero"`
Minimum *float64 `json:"minimum,omitempty"`
Maximum *float64 `json:"maximum,omitempty"`
ExclusiveMinimum *float64 `json:"exclusiveMinimum,omitempty"`
ExclusiveMaximum *float64 `json:"exclusiveMaximum,omitempty"`
MinLength *uint64 `json:"minLength,omitempty"`
MaxLength *uint64 `json:"maxLength,omitempty"`
MinItems *uint64 `json:"minItems,omitempty"`
MaxItems *uint64 `json:"maxItems,omitempty"`
UniqueItems bool `json:"uniqueItems,omitempty,omitzero"`
// ContentEncoding marks base64 payloads ([]byte fields), per JSON Schema 2020-12.
ContentEncoding string `json:"contentEncoding,omitempty,omitzero"`
}
Schema is the JSON Schema subset used for parameters, bodies and components. Numeric bounds are pointers so that zero is distinguishable from unset.
type SecurityRequirement ¶ added in v0.3.0
type SecurityRequirement []string
SecurityRequirement combines named schemes with AND. Multiple requirements in a security array are alternatives (OR). Only supported, scope-free schemes can be required. WithSecurity rejects empty requirements.
func (SecurityRequirement) MarshalJSON ¶ added in v0.3.0
func (requirement SecurityRequirement) MarshalJSON() ([]byte, error)
MarshalJSON encodes supported scheme references using OpenAPI's empty scope arrays.
type SecurityScheme ¶ added in v0.3.0
type SecurityScheme struct {
Description string
// contains filtered or unexported fields
}
SecurityScheme describes API key or HTTP authentication. The generator does not perform authentication; it documents the server's requirements.
func APIKeyScheme ¶ added in v0.3.0
func APIKeyScheme(name string, location APIKeyLocation) SecurityScheme
APIKeyScheme describes an API key passed in a header, query, or cookie. WithSecurityScheme validates the name and location when registering it.
func HTTPScheme ¶ added in v0.3.0
func HTTPScheme(scheme, bearerFormat string) SecurityScheme
HTTPScheme describes HTTP authentication, such as basic or bearer. The bearer format is optional and is valid only for the bearer scheme.
func (SecurityScheme) MarshalJSON ¶ added in v0.3.0
func (scheme SecurityScheme) MarshalJSON() ([]byte, error)
MarshalJSON renders a scheme created with APIKeyScheme or HTTPScheme.