stdocs

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 10, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

README

stdocs

CI Go Report Card Go Reference

stdocs turns a standard library net/http.ServeMux into a self-documenting API: register routes as usual, and it serves interactive documentation for them — Scalar, Swagger UI, Redoc, or Stoplight Elements at /docs — backed by a generated OpenAPI 3.0/3.1/3.2 document. Zero dependencies, no code generation: the patterns you already write are the source of truth.

mux := stdocs.New(stdocs.WithTitle("My API"))
mux.HandleFunc("GET /users/{id}", getUser)
mux.Mount() // docs UI at /docs/, spec at /docs/openapi.json
log.Fatal(http.ListenAndServe(":8080", mux))

That's it. stdocs walks your registered routes, generates an OpenAPI spec from your Go types, and serves a docs UI at /docs/.

The same generated document, rendered by each of the four bundled rich UIs — every one available CDN-pinned or fully embedded for air-gapped builds.

Table of contents

Features

  • Five UIs — a tiny dependency-free default (~1.6 KB, inline JS only), plus Scalar, Swagger UI, Redoc, and Stoplight Elements — each available as a CDN sub-package (version-pinned with SRI integrity hashes) or an air-gapped embedded sub-package.
  • Three OpenAPI versions — 3.0.4 (default), 3.1.2, and 3.2.0, all tested.
  • Reflection — Go types become JSON Schemas: pointers, slices, maps, generics, embedded structs, recursive types via $ref, json tags (including omitempty, omitzero, and ,string), json.Marshaler/encoding.TextMarshaler awareness.
  • Smart defaults — function names become summaries, the first path segment becomes the tag, path params are auto-included.
  • Security — bearer, basic, API key, OAuth 2.0 (including the 3.2 device flow). Unregistered scheme names are reported as errors.
  • Environment togglingmux.Mount(enabled)/mux.Docs(enabled) and WithDisabled(true) turn the docs on or off per environment, and Hidden()/Internal() + WithInternal(show) control per-route visibility — all without changing registered routes.
  • Try-it detectionFromDocs identifies requests coming from the docs consoles so your middleware can decide what they may do.
  • XSS-safe — the docs HTML is rendered through html/template.
  • Zero deps — only the Go standard library at runtime.

Install

go get github.com/FumingPower3925/stdocs

Requires Go 1.25 or later. stdocs follows the Go project's release support policy — the two most recent Go releases, currently 1.25 and 1.26 — and CI runs the full test suite on every patch release of both. The route patterns stdocs documents ("GET /users/{id}") are the method+path syntax that net/http.ServeMux gained in Go 1.22.

Usage

Routes are documented automatically from the pattern and the registered function name:

mux := stdocs.New(stdocs.WithTitle("My API"))
mux.HandleFunc("GET /users", listUsers)        // summary "List users", tag "Users"
mux.HandleFunc("GET /health", healthCheck)     // summary "Health check", tag "Health"

Pass route options to attach bodies, responses, tags, and security:

type User struct {
    ID    string `json:"id" doc:"Unique ID"`
    Name  string `json:"name"`
    Email string `json:"email,omitempty"`
}

type CreateUserRequest struct {
    Name string `json:"name"`
}

type APIError struct {
    Message string `json:"message"`
}

mux.HandleFunc("GET /users/{id}", getUser,
    stdocs.Summary("Get a user by ID"),
    stdocs.WithResponse(200, User{}),
    stdocs.WithResponse(404, APIError{}),
)

mux.HandleFunc("POST /users", createUser,
    stdocs.WithBody(CreateUserRequest{}),
    stdocs.WithResponse(201, User{}),
)
Field tags

Struct fields can carry documentation in tags, picked up when the type is reflected:

Tag Effect
doc:"…" (or description:"…") Sets the field's schema description
example:"…" Sets the field's example — parsed according to the field type, so example:"42" on an int emits the number 42
type Task struct {
    ID       string `json:"id" doc:"Unique task ID"`
    Priority int    `json:"priority" doc:"1 (low) to 5 (urgent)" example:"3"`
}

An example value that does not parse as the field's type panics at document-build time.

The default response

WithResponse(0, body) declares the OpenAPI default response — the catch-all entry consumers fall back to for undeclared status codes, conventionally the shared error shape:

mux.HandleFunc("GET /tasks/{id}", getTask,
    stdocs.WithResponse(200, Task{}),
    stdocs.WithResponse(0, APIError{}), // "default" in the document
)

For features stdocs does not expose directly, use the escape hatch:

mux := stdocs.New(
    stdocs.WithTitle("My API"),
    stdocs.WithOpenAPI(func(doc map[string]any) {
        doc["info"].(map[string]any)["x-logo"] = map[string]any{
            "url": "https://example.com/logo.png",
        }
    }),
)

To pin the spec to a specific OpenAPI version, use WithVersion:

mux := stdocs.New(
    stdocs.WithTitle("My API"),
    stdocs.WithVersion(stdocs.OpenAPI32),  // 3.2.0
)

stdocs ships the latest patch of each minor (OpenAPI30 = 3.0.4, OpenAPI31 = 3.1.2, OpenAPI32 = 3.2.0). For 3.2 you can additionally set the document's canonical URI:

mux := stdocs.New(
    stdocs.WithTitle("My API"),
    stdocs.WithVersion(stdocs.OpenAPI32),
    stdocs.WithSelfURL("https://example.com/openapi.json"),
)

The full option list lives on pkg.go.dev.

Mounting and disabling the docs

mux.Mount() is shorthand for registering the handler returned by mux.Docs() on the mux itself at the configured docs prefix — there is one docs handler, two ways to place it. Use Mount() unless you need the handler directly (to wrap it in auth middleware or mount it on another mux). Both accept the same optional bool with the same rule: an explicit per-call value wins over WithDisabled in both directions.

The docs UI and the spec endpoints (openapi.json, openapi.yaml) can be turned off without unregistering routes. The decision is taken when Mount()/Docs() is called (wrap the handler yourself if you need a per-request switch):

// 1) Per-mux: WithDisabled(true) makes Mount a no-op and Docs return
//    a 404 handler everywhere.
mux := stdocs.New(
    stdocs.WithTitle("My API"),
    stdocs.WithDisabled(os.Getenv("ENV") == "prod"),
)
mux.HandleFunc("GET /users", listUsers)
mux.Mount() // registers nothing when disabled
// 2) Per-call: pass the condition to Mount (or to Docs when
//    mounting manually).
mux := stdocs.New(stdocs.WithTitle("My API"))
mux.HandleFunc("GET /users", listUsers)
mux.Mount(os.Getenv("ENV") != "prod")

When disabled, every request under the docs prefix gets a 404. The spec is still buildable via mux.JSON() and mux.YAML() — disabling the UI does not stop spec generation. Routes registered under the docs prefix (the docs page itself, asset handlers) never appear in the generated spec.

Hiding individual routes

Per-route visibility composes with the switches above: Hidden() excludes a route from the document everywhere, and Internal() excludes it unless the mux was built with WithInternal(true) (when shown, the operation carries x-internal: true, the extension spec-filtering tools understand). A complete environment setup:

env := os.Getenv("ENV")
mux := stdocs.New(
    stdocs.WithTitle("My API"),
    stdocs.WithDisabled(env == "prod"), // prod: no docs at all
    stdocs.WithInternal(env == "dev"),  // dev: full docs; elsewhere internal routes are hidden
)
mux.HandleFunc("GET /users", listUsers)                           // always documented
mux.HandleFunc("POST /admin/keys", rotateKeys, stdocs.Internal()) // documented only in dev
mux.HandleFunc("GET /healthz", healthCheck, stdocs.Hidden())      // never documented
mux.Mount()

Excluded routes leave no trace in the document — no paths, no schemas, no operation ids. Visibility only shapes the published documentation: hidden and internal routes still serve traffic in every environment. It is not access control; protect sensitive endpoints with real authentication.

Detecting try-it requests

The rich UIs' "Try it out" / "Test Request" consoles send real requests to your backend — on the wire they are indistinguishable from any other client. FromDocs identifies them (best-effort, via the Referer header the browser attaches to the docs page's fetches) so your team can decide the policy: block writes, route them to a scratch datastore, tag them for observability, or anything else.

guard := func(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodGet && mux.FromDocs(r) {
            http.Error(w, "try-it requests cannot modify data", http.StatusForbidden)
            return
        }
        next.ServeHTTP(w, r)
    })
}
log.Fatal(http.ListenAndServe(":8080", guard(mux)))

FromDocs is a guardrail against accidents, not a security control: the Referer header is client-controlled (it can be forged) and strippable (privacy extensions, a strict Referrer-Policy). It also only works when the docs page and the API share an origin — with an absolute WithServer URL on another host, browsers send an origin-only Referer by default and detection reports false. Use it only to restrict what docs-originated traffic may do — never to grant access or skip authentication.

If you have a hand-written OpenAPI document instead of generated routes, serve it with DocsHandler + WithSpec:

spec, _ := os.ReadFile("openapi.json")
http.Handle("GET /docs/", stdocs.DocsHandler(
    stdocs.WithTitle("My API"),
    stdocs.WithSpec(spec),
))

UIs

The default UI is a tiny dependency-free HTML page (~1.6 KB, inline JS only, no external assets). To use a richer UI, import a sub-package and pass its WithUI() option:

import "github.com/FumingPower3925/stdocs/ui/scalar"

mux := stdocs.New(stdocs.WithTitle("My API"), scalar.WithUI())

For an air-gapped build (no CDN), import the matching *emb sub-package and mount its AssetHandler():

import "github.com/FumingPower3925/stdocs/ui/scalaremb"

mux := stdocs.New(stdocs.WithTitle("My API"), scalaremb.WithUI())
mux.Mount()
mux.Handle("GET /docs/_assets/",
    http.StripPrefix("/docs/_assets/", scalaremb.AssetHandler()))

Each rich UI comes in two flavors:

UI CDN sub-package Embedded sub-package
(default) (built-in, ~1.6 KB)
Scalar ui/scalar (~3.6 MB from the CDN) ui/scalaremb (~3.6 MB in your binary)
Swagger UI ui/swaggerui (~1.7 MB from the CDN) ui/swaggeruiemb (~1.7 MB in your binary)
Redoc ui/redoc (~1.1 MB from the CDN) ui/redocemb (~1.1 MB in your binary)
Stoplight ui/stoplight (~2.4 MB from the CDN) ui/stoplightemb (~2.4 MB in your binary)

All CDN URLs are pinned to exact versions with sha384 SRI integrity hashes. Sub-packages are not linked into your binary unless imported.

Using the spec downstream

The generated document is not just for the docs page: mux.JSON() and mux.YAML() hand you the exact bytes served at the spec endpoints, and the output is deterministic by construction — keys are sorted and operationIds and component names are stable across rebuilds — so it works as a committed artifact.

The recommended pattern is a golden-file test:

var update = flag.Bool("update", false, "rewrite openapi.json")

func TestOpenAPIGolden(t *testing.T) {
    got, err := NewAPI().JSON() // your mux constructor
    if err != nil {
        t.Fatal(err)
    }
    const golden = "openapi.json"
    if *update {
        if err := os.WriteFile(golden, got, 0o644); err != nil {
            t.Fatal(err)
        }
    }
    want, err := os.ReadFile(golden)
    if err != nil {
        t.Fatalf("%v (run: go test -run TestOpenAPIGolden -update)", err)
    }
    if !bytes.Equal(got, want) {
        t.Fatalf("openapi.json is stale; run: go test -run TestOpenAPIGolden -update")
    }
}

Every API change now shows up as a reviewable diff to openapi.json in the PR, and the committed file feeds the rest of the toolchain without running the server:

  • Contract diffing — e.g. oasdiff breaking old.json openapi.json in CI flags breaking changes.
  • Lintingspectral lint openapi.json (or Redocly CLI) enforces API style rules.
  • Client generation — point openapi-generator, oapi-codegen, or your SDK pipeline at the committed file to produce typed clients in any language.

How it works

Go 1.22's net/http.ServeMux supports method+path patterns but does not expose them publicly. stdocs.New() returns a *stdocs.Mux that embeds *http.ServeMux and intercepts Handle/HandleFunc calls to record pattern + metadata. On the first request to /docs/openapi.json, the registry is walked and the spec is built and cached (call mux.Refresh() to rebuild).

No comments, no code generation, no unsafe — the pattern string is the documentation.

A runnable demo lives in cmd/demo:

go run ./cmd/demo
# open http://localhost:8080/docs/

Scope and non-goals

stdocs does one thing: it documents stdlib net/http.ServeMux applications and serves the result. Knowing the boundaries up front saves you an evaluation:

  • stdlib only. There are no gin/echo/chi/fiber integrations and there will be none — the wrapped ServeMux is the design, not a first adapter.
  • Documentation, not enforcement. stdocs does not validate requests, bind parameters, or check that handlers honor the documented contract. The document describes intent; keeping handlers honest is the application's job (the golden-file workflow above makes drift reviewable).
  • No code generation, no comment annotations, no dependencies. Permanently, by design.
  • The built-in UI stays minimal. The default page is a ~1.6 KB dependency-free route list without a try-it console — that smallness is its feature. All four rich UIs ship consoles and are one import away.

When something else fits better: if the contract is your deliverable (cross-team spec reviews, multi-language clients, enforced conformance), a spec-first generator like oapi-codegen or ogen is the right tool; if you are greenfield and want validation enforced from types, a typed-handler framework like huma is. stdocs is for the code you already have.

Contributing

See CONTRIBUTING.md. Translations are community-maintained; see the "Translations" section there to add or update one.

go test -race -count=1 ./...
golangci-lint run ./...

License

Apache-2.0. See LICENSE.

Documentation

Overview

Package stdocs turns a standard library net/http.ServeMux into a self-documenting API: routes registered on the wrapped mux are served as interactive documentation — a /docs UI rendered by Scalar, Swagger UI, Redoc, Stoplight Elements, or a built-in page — backed by a generated OpenAPI 3.0, 3.1, or 3.2 document.

The pattern syntax it documents ("GET /users/{id}") is the method+path routing introduced in Go 1.22. The module supports the two most recent Go releases, matching the Go project's release policy. There are no dependencies beyond the standard library and no code generation: the patterns you already write are the source of truth.

Two ways to use it

  • New returns a Mux — an *http.ServeMux wrapper that records route metadata as you register handlers and generates the OpenAPI document from it. This is the recommended way to use stdocs.

  • DocsHandler serves a docs UI for a hand-written OpenAPI document supplied via WithSpec, without introspecting any mux.

Example

type User struct {
    ID   string `json:"id"`
    Name string `json:"name"`
}

func getUser(w http.ResponseWriter, r *http.Request) { /* ... */ }

func main() {
    mux := stdocs.New(
        stdocs.WithTitle("My API"),
        stdocs.WithVersion(stdocs.OpenAPI31),
        stdocs.WithBearerAuth("bearerAuth", "JWT"),
    )
    mux.HandleFunc("GET /users/{id}", getUser,
        stdocs.Summary("Get user by id"),
        stdocs.WithResponse(200, User{}),
        stdocs.WithSecurity("bearerAuth"),
    )
    mux.Mount() // docs UI at /docs/, spec at /docs/openapi.json
    log.Fatal(http.ListenAndServe(":8080", mux))
}

Serve the mux itself (it is the http.Handler for your routes). To mount it under a sub-path, wrap it with net/http.StripPrefix — note the generated spec paths will not include the stripped prefix.

Options and route opts

Mux-level configuration uses Option values passed to New or DocsHandler (all named With*, e.g. WithTitle, WithVersion, WithDocsPrefix, WithDisabled). Per-route documentation uses RouteOpt values passed to Mux.HandleFunc / Mux.Handle: bare-named opts set simple operation metadata (Summary, Description, Tags, Deprecated, OperationID, Optional, Hidden, Internal), while opts that attach bodies, responses, parameters, or security are named With* (WithBody, WithResponse, WithParam, WithSecurity, ...).

Scope and non-goals

stdocs documents stdlib ServeMux applications; it does not integrate with third-party routers, does not validate requests or enforce the documented contract at runtime, and uses no code generation, comment annotations, or dependencies — permanently, by design. The document describes intent; keeping handlers honest is the application's job.

OpenAPI versions

stdocs emits the latest patch of each supported minor: OpenAPI30 (3.0.4, the default), OpenAPI31 (3.1.2), and OpenAPI32 (3.2.0). Select one with WithVersion. For 3.2, WithSelfURL sets the document's canonical URI ($self).

Index

Examples

Constants

View Source
const (
	SecurityHTTP           = spec.SecurityHTTP
	SecurityAPIKey         = spec.SecurityAPIKey
	SecurityOAuth2         = spec.SecurityOAuth2
	SecurityOpenIDConnect  = spec.SecurityOpenIDConnect
	SecurityAPIKeyInHeader = spec.SecurityAPIKeyInHeader
	SecurityAPIKeyInQuery  = spec.SecurityAPIKeyInQuery
	SecurityAPIKeyInCookie = spec.SecurityAPIKeyInCookie
)
View Source
const (
	// OpenAPI30 is the latest 3.0.x patch (3.0.4), the default.
	OpenAPI30 = version.OpenAPI30
	// OpenAPI31 is the latest 3.1.x patch (3.1.2).
	OpenAPI31 = version.OpenAPI31
	// OpenAPI32 is the latest 3.2.x patch (3.2.0).
	OpenAPI32 = version.OpenAPI32
)

The version constants accepted by WithVersion: the latest patch of each supported OpenAPI minor.

Variables

This section is empty.

Functions

func DocsHandler

func DocsHandler(opts ...Option) http.Handler

DocsHandler returns an http.Handler that serves the docs UI and a static OpenAPI spec. This is the Tier-1 entry point: it does not introspect any mux. Provide the document with WithSpec; without it, a minimal valid placeholder built from WithTitle / WithAPIVersion / WithVersion is served, so every bundled UI still renders.

The handler serves:

GET <prefix>/             -> the HTML docs UI
GET <prefix>/openapi.json -> the spec as JSON
GET <prefix>/openapi.yaml -> the spec as YAML

To customise the docs UI, pass a UI option from one of the github.com/FumingPower3925/stdocs/ui/* sub-packages:

mux := http.NewServeMux()
mux.Handle("GET /docs/", stdocs.DocsHandler(
    stdocs.WithTitle("My API"),
    scalar.WithUI(),
))
mux.HandleFunc("GET /users", listUsers)

If you want a spec generated from registered routes instead, use Tier 2: build the application on a *stdocs.Mux (see New).

If WithDisabled(true) is passed, the returned handler responds with 404 on every request, equivalent to Mux.Docs(false).

Example

Serving a docs UI for a hand-written spec (Tier 1) — no route introspection involved.

package main

import (
	"fmt"
	"net/http"

	"github.com/FumingPower3925/stdocs"
)

func main() {
	spec := []byte(`{"openapi":"3.0.4","info":{"title":"Hand-written","version":"1.0.0"},"paths":{}}`)

	mux := http.NewServeMux()
	mux.Handle("GET /docs/", stdocs.DocsHandler(
		stdocs.WithTitle("Hand-written"),
		stdocs.WithSpec(spec),
	))
	fmt.Println("docs mounted")
}
Output:
docs mounted

func FromDocs added in v0.2.0

func FromDocs(r *http.Request, docsPrefix string) bool

FromDocs reports whether r appears to originate from the interactive docs UI served under docsPrefix — that is, from a "Try it out" / "Test Request" console on the docs page rather than from a regular API client. An empty (or all-slash) docsPrefix means the default "/docs".

Detection is based on the Referer header: browsers attach the docs page's URL to the fetch calls the consoles make. The check matches on the URL path only, so it keeps working behind reverse proxies that add their own path prefix (a page at /api/docs/ still matches a docs prefix of "/docs").

FromDocs is a convenience guardrail, NOT a security control. The Referer header is fully client-controlled: a caller can forge it (false positives), and there are false negatives too — privacy extensions or a strict Referrer-Policy can strip the header, and try-it requests sent to a DIFFERENT origin (an absolute WithServer URL on another host) carry an origin-only Referer under browsers' default policy, so FromDocs reports false for them (Scalar additionally routes cross-origin try-it calls through its own proxy). Detection is reliable only when the docs page and the API share an origin — the normal stdocs setup, where one mux serves both. Use FromDocs only to RESTRICT what docs-originated traffic may do — never to grant access, skip authentication, or relax validation. Endpoints that must not be mutated by strangers need real authentication regardless.

The intended use is a small middleware in front of the mux:

guard := func(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodGet && stdocs.FromDocs(r, "/docs") {
            http.Error(w, "try-it requests cannot modify data", http.StatusForbidden)
            return
        }
        next.ServeHTTP(w, r)
    })
}
log.Fatal(http.ListenAndServe(":8080", guard(mux)))

Teams that prefer other policies can branch on FromDocs however they like: route writes to a scratch datastore, add a dry-run flag, tag the request for observability, and so on.

Example

Restricting what try-it consoles may do: the docs page's "Try it out" buttons send real requests, identified (best-effort) by their Referer. FromDocs gates a restriction — never use it to grant access, since the header is client-controlled.

package main

import (
	"fmt"
	"net/http"

	"github.com/FumingPower3925/stdocs"
)

func main() {
	mux := stdocs.New(stdocs.WithTitle("My API"))
	mux.HandleFunc("POST /users", func(w http.ResponseWriter, r *http.Request) {})
	mux.Mount()

	guard := func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Method != http.MethodGet && mux.FromDocs(r) {
				http.Error(w, "try-it requests cannot modify data", http.StatusForbidden)
				return
			}
			next.ServeHTTP(w, r)
		})
	}
	_ = guard // pass guard(mux) to http.ListenAndServe

	r, _ := http.NewRequest(http.MethodPost, "/users", nil)
	r.Header.Set("Referer", "https://api.example.com/docs/")
	fmt.Println("from docs:", mux.FromDocs(r))
}
Output:
from docs: true

Types

type Config

type Config struct {
	// Info carries the OpenAPI "info" object.
	Info Info
	// Servers is the list of OpenAPI "servers".
	Servers []Server
	// Tags are the declared top-level tags. Tags attached to operations
	// that aren't in this list are still emitted on the operation; the
	// declarations are just for richer descriptions.
	Tags []TagDecl
	// DocsPrefix is the URL prefix under which the docs UI and spec are
	// served. Defaults to "/docs".
	DocsPrefix string
	// SelfURL is the OpenAPI 3.2 "$self" field — the canonical URI
	// of the document. When non-empty, the 3.2 emitter includes it
	// in the spec root. Ignored for 3.0 and 3.1 (the field does
	// not exist in those versions).
	SelfURL string
	// Version is the OpenAPI version to emit. Defaults to OpenAPI30.
	Version SpecVersion
	// DefaultSummary is a fallback summary used for routes that have
	// neither a per-route Summary nor a function-name-based inference.
	DefaultSummary string
	// UIDoc is the HTML template for the docs UI page. The default is
	// the small dependency-free page in stdocs.defaultUIDoc. UI
	// sub-packages override this field via a stdocs.Option to swap in
	// their own page. The template may contain {{.Title}} and
	// {{.SpecURL}} placeholders; the page is rendered once, when the
	// docs handler is constructed.
	UIDoc string
	// Hooks is the list of post-build callbacks registered via
	// WithOpenAPI. Each is called once per spec build, with the
	// emitted spec as a map[string]any, and may mutate it in place.
	Hooks []func(doc map[string]any)
	// Security is the list of registered security schemes. The user
	// adds entries via WithSecurityScheme / WithBearerAuth / etc.;
	// each is rendered into components.securitySchemes at build time.
	Security []spec.NamedSecurityScheme
	// GlobalSecurity is the default security requirement applied to
	// every operation. Operations may override with WithSecurity or
	// opt out with WithNoSecurity.
	GlobalSecurity []SecurityRequirement
	// Webhooks are emitted for 3.1 and 3.2 specs and ignored for 3.0
	// (the field does not exist there). The map is keyed by webhook
	// name.
	Webhooks map[string]Webhook
	// Disabled turns off the docs handler. When true, Mux.Docs and
	// DocsHandler return a 404 handler instead of serving the UI and
	// the spec. Mux.Mount respects this and registers nothing.
	Disabled bool
	// StaticSpec is a hand-written OpenAPI document (JSON bytes) set
	// via WithSpec. It is served verbatim by DocsHandler (Tier 1) and
	// ignored by *Mux (Tier 2), which generates its own document.
	StaticSpec []byte
	// ShowInternal controls whether routes marked with the Internal
	// route opt appear in the generated document. Defaults to false
	// (internal routes hidden). Set via WithInternal.
	ShowInternal bool
}

Config holds the resolved configuration for an stdocs Mux. It is built by applying a list of Options to a fresh Config and is shared with the registry and the spec emitter.

Config is exported (rather than unexported like in many libraries) so that UI sub-packages (e.g. stdocs/ui/scalar) can mutate it via a stdocs.Option. UI sub-packages should not construct or copy a Config; they should only read or write the UIDoc field.

type Contact

type Contact = spec.Contact

Contact is the OpenAPI "info.contact" object. Fields: Name, URL, Email. Set via WithContact; empty fields are omitted from the document.

type Info

type Info = spec.Info

Info is the OpenAPI "info" object. Fields: Title, Version, Description, TermsOfService, Contact (*Contact), License (*License). Title and Version are set via WithTitle and WithAPIVersion.

type License

type License = spec.License

License is the OpenAPI "info.license" object. Fields: Name, URL. Set via WithLicense; empty fields are omitted.

type Mux

type Mux struct {
	*http.ServeMux
	// contains filtered or unexported fields
}

Mux is an *http.ServeMux that also records route metadata for OpenAPI generation. Use stdocs.New to construct one. Mux embeds *http.ServeMux, so all its methods are available transparently.

func New

func New(opts ...Option) *Mux

New returns a *stdocs.Mux ready to register routes on.

Example

The simplest possible setup: wrap the mux, register routes, mount the docs, serve. The generated document is available programmatically through JSON() too.

package main

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/FumingPower3925/stdocs"
)

func main() {
	mux := stdocs.New(stdocs.WithTitle("My API"))
	mux.HandleFunc("GET /users/{id}", func(w http.ResponseWriter, r *http.Request) {})
	mux.Mount() // docs UI at /docs/, spec at /docs/openapi.json

	b, _ := mux.JSON()
	var doc struct {
		OpenAPI string `json:"openapi"`
		Info    struct {
			Title string `json:"title"`
		} `json:"info"`
	}
	_ = json.Unmarshal(b, &doc)
	fmt.Println(doc.OpenAPI, doc.Info.Title)
}
Output:
3.0.4 My API

func (*Mux) Config

func (m *Mux) Config() *Config

Config returns the resolved configuration for the mux. It is useful for UI sub-packages that need to read or override Config fields.

func (*Mux) Docs

func (m *Mux) Docs(enabled ...bool) http.Handler

Docs returns an http.Handler that serves the docs UI and the OpenAPI spec for this mux. The returned handler is a sub-mux that internally serves:

GET <prefix>/             -> the HTML docs UI
GET <prefix>/openapi.json -> the spec as JSON
GET <prefix>/openapi.yaml -> the spec as YAML

In most setups, call Mount instead, which registers this handler at the configured docs prefix (default "/docs", changeable via WithDocsPrefix). When mounting manually, the registration pattern must match the configured prefix:

mux.ServeMux.Handle("GET /docs/", mux.Docs())

(Plain mux.Handle works too — routes under the docs prefix are excluded from the generated spec.)

The optional bool argument enables per-call toggling: pass false to get a handler that responds 404 to everything, pass true to force the docs on, or omit it to follow the WithDisabled config. An explicit per-call value wins over WithDisabled in both directions. Only the first value is consulted; passing more than one bool panics.

mux.ServeMux.Handle("GET /docs/", mux.Docs(os.Getenv("ENV") != "prod"))

The decision is taken when Docs is called. For a per-request switch, wrap the returned handler in your own middleware.

Example

Turning the docs off per environment without touching routes.

package main

import (
	"fmt"
	"net/http"

	"github.com/FumingPower3925/stdocs"
)

func main() {
	prod := true
	mux := stdocs.New(stdocs.WithTitle("My API"))
	mux.HandleFunc("GET /users", func(w http.ResponseWriter, r *http.Request) {})

	// An explicit per-call value wins over WithDisabled in both
	// directions; mux.Docs(false) serves 404 for every docs request.
	mux.ServeMux.Handle("GET /docs/", mux.Docs(!prod))
	fmt.Println("docs enabled:", !prod)
}
Output:
docs enabled: false

func (*Mux) FromDocs added in v0.2.0

func (m *Mux) FromDocs(r *http.Request) bool

FromDocs reports whether r appears to originate from this mux's docs UI. It is FromDocs(r, prefix) with the mux's configured docs prefix; see the package-level FromDocs for the detection mechanics and the security caveats.

func (*Mux) Handle

func (m *Mux) Handle(p string, h http.Handler, opts ...RouteOpt)

Handle registers h for the given pattern. The handler's underlying function name cannot be recovered from an http.Handler, so routes registered via Handle do not benefit from function-name-based summary inference (they get a blank summary unless Summary is provided).

func (*Mux) HandleFunc

func (m *Mux) HandleFunc(p string, h func(http.ResponseWriter, *http.Request), opts ...RouteOpt)

HandleFunc registers h for the given pattern. opts are RouteOpts that document the route.

The pattern must be a Go 1.22+ ServeMux pattern (e.g. "GET /users/{id}"). If parsing fails, HandleFunc panics. This matches the stdlib's behavior of panicking on invalid patterns.

func (*Mux) JSON

func (m *Mux) JSON() ([]byte, error)

JSON returns the OpenAPI spec as JSON bytes. The version depends on the mux's configured Version. First call is cached.

func (*Mux) Mount

func (m *Mux) Mount(enabled ...bool)

Mount registers the docs handler on the mux itself, at the configured DocsPrefix (default "/docs"). It registers exact patterns for the docs page and the two spec endpoints — plus a subtree fallback — so a user route like "GET /docs/{file}" can never shadow the spec endpoints (exact literals win over wildcards in ServeMux).

The optional bool argument mirrors Docs: pass false to register nothing, pass true to register the docs even on a mux disabled via WithDisabled, or omit it to follow the WithDisabled config. An explicit per-call value wins over WithDisabled in both directions. Only one bool is accepted; passing more panics.

mux.Mount(os.Getenv("ENV") != "prod")

Calling Mount more than once is a no-op after the first call that registered the docs. Call it after registering all routes.

func (*Mux) Refresh

func (m *Mux) Refresh()

Refresh invalidates the spec cache, forcing the next call to JSON or YAML to rebuild.

func (*Mux) YAML

func (m *Mux) YAML() ([]byte, error)

YAML returns the OpenAPI spec as YAML bytes. YAML emission is a hand-rolled minimal converter; only the fields we emit are supported.

type OAuthFlow

type OAuthFlow = spec.OAuthFlow

OAuthFlow describes one OAuth 2.0 flow. Fields: AuthorizationURL, TokenURL, RefreshURL, DeviceAuthorizationURL (3.2 device flow only), and Scopes (scope name -> description; always emitted, required by the spec).

type OAuthFlows

type OAuthFlows = spec.OAuthFlows

OAuthFlows groups the OAuth 2.0 flows of a scheme: Implicit, Password, ClientCredentials, AuthorizationCode, and (OpenAPI 3.2 only) DeviceAuthorization — each an optional *OAuthFlow.

type Operation

type Operation = spec.Operation

Operation is the per-route OpenAPI operation under construction. It is the value RouteOpts mutate; most users never touch it directly.

type Option

type Option func(*Config)

Option is a function that mutates a config. Options are applied by New and DocsHandler at construction time.

func WithAPIKeyAuth

func WithAPIKeyAuth(name, in, paramName string) Option

WithAPIKeyAuth is a convenience for API key authentication. in is one of stdocs.SecurityAPIKeyInHeader, stdocs.SecurityAPIKeyInQuery, stdocs.SecurityAPIKeyInCookie.

func WithAPIVersion

func WithAPIVersion(v string) Option

WithAPIVersion sets the API version string in the OpenAPI "info" block (e.g. "1.0.0"). This is independent of WithVersion which sets the OpenAPI specification version (3.0.4 vs 3.1.2 vs 3.2.0).

func WithBasicAuth

func WithBasicAuth(name string) Option

WithBasicAuth is a convenience for HTTP basic authentication.

func WithBearerAuth

func WithBearerAuth(name, bearerFormat string) Option

WithBearerAuth is a convenience for HTTP bearer authentication.

Example

Registering a security scheme and requiring it on a route.

package main

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/FumingPower3925/stdocs"
)

func main() {
	mux := stdocs.New(
		stdocs.WithTitle("My API"),
		stdocs.WithBearerAuth("bearerAuth", "JWT"),
		stdocs.WithGlobalSecurity("bearerAuth"),
	)
	mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {},
		stdocs.WithNoSecurity(), // public route opts out of the global scheme
	)

	b, _ := mux.JSON()
	var doc struct {
		Paths map[string]map[string]struct {
			Security []map[string][]string `json:"security"`
		} `json:"paths"`
	}
	_ = json.Unmarshal(b, &doc)
	fmt.Println(len(doc.Paths["/health"]["get"].Security))
}
Output:
0

func WithContact

func WithContact(name, email, url string) Option

WithContact sets the contact info.

func WithDefaultSummary

func WithDefaultSummary(template string) Option

WithDefaultSummary sets a default summary template used for routes that do not provide one and whose function name does not yield a useful inference. Use {resource} as a placeholder for the first path segment (the inferred tag).

func WithDescription

func WithDescription(s string) Option

WithDescription sets the API description.

func WithDisabled

func WithDisabled(disabled bool) Option

WithDisabled turns off the docs UI and the spec endpoints. Useful for environment-based toggling (e.g. don't expose docs in production, or behind a feature flag):

mux := stdocs.New(
    stdocs.WithDisabled(os.Getenv("ENV") == "prod"),
)

When the mux is disabled, Mux.Docs returns a 404 handler and Mux.Mount registers nothing. JSON and YAML still produce the spec bytes — disabling the docs UI does not stop spec generation.

For per-call toggling (e.g. a config that may change at runtime), pass the bool directly to Mux.Docs(enabled) instead.

func WithDocsPrefix

func WithDocsPrefix(prefix string) Option

WithDocsPrefix overrides the URL prefix for the docs UI. The default is "/docs". The value is normalized: a leading slash is added if missing, and a trailing slash is removed so the prefix is comparable to strings.TrimPrefix results. An empty prefix is replaced with the default "/docs"; to turn the docs UI off, use WithDisabled or pass false to Mux.Docs.

The root prefix "/" is rejected with a panic: it would claim the whole URL space and produce an invalid ServeMux pattern in Mount.

func WithGlobalSecurity

func WithGlobalSecurity(name string, scopes ...string) Option

WithGlobalSecurity sets the default security requirement applied to every operation that does not specify its own. Operations can opt out with stdocs.WithNoSecurity or override with stdocs.WithSecurity.

stdocs.WithGlobalSecurity("bearerAuth")
stdocs.WithGlobalSecurity("oauth2Auth", "read:users")

func WithInternal added in v0.1.1

func WithInternal(show bool) Option

WithInternal sets whether routes marked with the Internal route opt appear in the generated OpenAPI document. The default is false: internal routes are hidden, so forgetting this option can never leak a sensitive endpoint into a published spec. When shown, internal operations carry an "x-internal": true extension.

Typical environment wiring, together with WithDisabled:

env := os.Getenv("ENV")
mux := stdocs.New(
    stdocs.WithDisabled(env == "prod"),  // prod: no docs at all
    stdocs.WithInternal(env == "dev"),   // dev: everything; staging: internal hidden
)

Visibility only shapes the published documentation; hidden and internal routes still serve traffic in every environment.

func WithLicense

func WithLicense(name, url string) Option

WithLicense sets the license info.

func WithOAuth2Auth

func WithOAuth2Auth(name string, flows OAuthFlows) Option

WithOAuth2Auth is a convenience for OAuth 2.0 with one or more flows.

func WithOpenAPI

func WithOpenAPI(fn func(doc map[string]any)) Option

WithOpenAPI registers a callback that runs after the spec is built and before it is cached. The callback receives the spec as a map[string]any and may mutate it in place. This is the escape hatch for features stdocs does not expose directly: security schemes, webhooks, custom x-extensions, vendor extensions, etc.

The callback is invoked once per build (i.e. once before the cache is populated; subsequent reads use the cache). Call Refresh to force the callback to run again.

Example:

stdocs.WithOpenAPI(func(doc map[string]any) {
    doc["security"] = []map[string]any{{
        "bearerAuth": []string{},
    }}
    doc["components"].(map[string]any)["securitySchemes"] = map[string]any{
        "bearerAuth": map[string]any{
            "type":         "http",
            "scheme":       "bearer",
            "bearerFormat": "JWT",
        },
    }
})

func WithSecurityScheme

func WithSecurityScheme(name string, scheme SecurityScheme) Option

WithSecurityScheme registers a security scheme under the given name. The name is the key in the components.securitySchemes map and is the value you pass to WithSecurity on a route. If name is empty, a sensible default is chosen (e.g. "bearerAuth" for HTTP bearer).

Use the chosen name with WithSecurity to require this scheme on a route.

func WithSelfURL

func WithSelfURL(selfURL string) Option

WithSelfURL sets the OpenAPI 3.2 "$self" field. This is the canonical URI of the document. It is emitted only in 3.2 specs; setting it on a 3.0 or 3.1 mux has no effect because those versions do not have the field.

The value must be a valid RFC 3986 URI reference without a fragment (both constraints come from the OpenAPI 3.2 specification and its published JSON Schema). WithSelfURL panics on invalid input, consistent with WithVersion's fail-fast behavior at New()/DocsHandler() time.

func WithServer

func WithServer(url, description string) Option

WithServer adds a server entry.

func WithSpec

func WithSpec(specJSON []byte) Option

WithSpec sets a static OpenAPI document (JSON bytes) for DocsHandler to serve at <prefix>/openapi.json (and, converted, at <prefix>/openapi.yaml). This is the Tier-1 path for exposing a hand-written spec through the docs UI:

specJSON, _ := os.ReadFile("openapi.json")
mux.Handle("GET /docs/", stdocs.DocsHandler(
    stdocs.WithTitle("My API"),
    stdocs.WithSpec(specJSON),
))

WithSpec has no effect on *stdocs.Mux (Tier 2), which always generates its spec from the registered routes.

func WithTag

func WithTag(name, description string) Option

WithTag declares a top-level tag and its description. Tags attached to operations that match a declared tag are also valid; undeclared tags are still emitted.

func WithTitle

func WithTitle(title string) Option

WithTitle sets the API title. The default is "API".

func WithVersion

func WithVersion(v SpecVersion) Option

WithVersion sets the OpenAPI spec version. Accepts OpenAPI30 (3.0.4), OpenAPI31 (3.1.2), or OpenAPI32 (3.2.0). A string literal like "3.0.4" is also accepted because SpecVersion is a defined string type with the same underlying values.

WithVersion panics on an unknown version string. Options run at New()/DocsHandler() time, the same fail-fast window where bad patterns already panic; silently coercing to a default would mask user errors.

Example

Selecting the OpenAPI version. stdocs ships the latest patch of each supported minor: 3.0.4 (default), 3.1.2, and 3.2.0.

package main

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/FumingPower3925/stdocs"
)

func main() {
	mux := stdocs.New(
		stdocs.WithTitle("My API"),
		stdocs.WithVersion(stdocs.OpenAPI32),
		stdocs.WithSelfURL("https://api.example.com/openapi.json"),
	)
	mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {})

	b, _ := mux.JSON()
	var doc struct {
		OpenAPI string `json:"openapi"`
		Self    string `json:"$self"`
	}
	_ = json.Unmarshal(b, &doc)
	fmt.Println(doc.OpenAPI, doc.Self)
}
Output:
3.2.0 https://api.example.com/openapi.json

func WithWebhooks

func WithWebhooks(hooks map[string]Webhook) Option

WithWebhooks registers one or more webhooks under their given names. Webhooks require OpenAPI 3.1 or 3.2; on 3.0 they are silently ignored (the field does not exist in that version).

Webhook payloads are described the same way route bodies are: set RequestBody.BodyValue (or Response.BodyValue) to a zero value of the Go type and its JSON Schema is reflected when the document is built.

Example:

type UserPayload struct {
    ID string `json:"id"`
}

stdocs.WithWebhooks(map[string]stdocs.Webhook{
    "newUser": {
        Method:      "POST",
        Summary:     "New user created",
        RequestBody: &stdocs.RequestBody{Required: true, BodyValue: UserPayload{}},
        Responses: map[string]*stdocs.Response{
            "200": {Description: "OK"},
        },
    },
})

type Param

type Param = spec.Param

Param describes one OpenAPI parameter. Fields: Name, In ("path", "query", "header", "cookie"), Required, Description, Schema. Usually created via WithParam / QueryParam / HeaderParam / CookieParam.

type PathItem

type PathItem = spec.PathItem

PathItem groups the operations of one path. Produced internally by the registry; exposed for advanced use only.

type RequestBody

type RequestBody = spec.RequestBody

RequestBody describes an operation's request body. Fields: Description, Required, ContentType (defaults to "application/json"), Example, and BodyValue — a zero value of the Go body type, reflected at document-build time. Usually created via WithBody; constructed directly only for webhooks.

type Response

type Response = spec.Response

Response describes one entry of an operation's "responses" map. Fields: Status, Description, Headers, Example, and BodyValue — a zero value of the Go response type, reflected into a JSON Schema at document-build time. Usually created via WithResponse and decorated with WithResponseDescription / WithResponseHeader / WithResponseExample; constructed directly only for webhooks.

type RouteOpt

type RouteOpt func(*route)

RouteOpt is a function that mutates a route's metadata. RouteOpt is passed as variadic to *stdocs.Mux.HandleFunc and *stdocs.Mux.Handle.

func CookieParam

func CookieParam(name, typ, desc string) RouteOpt

CookieParam is shorthand for WithParam(name, "cookie", typ, desc).

func Deprecated

func Deprecated() RouteOpt

Deprecated marks the route as deprecated.

func Description

func Description(s string) RouteOpt

Description sets the route's longer Markdown description.

func HeaderParam

func HeaderParam(name, typ, desc string) RouteOpt

HeaderParam is shorthand for WithParam(name, "header", typ, desc).

func Hidden added in v0.1.1

func Hidden() RouteOpt

Hidden excludes the route from the generated OpenAPI document unconditionally, in every environment. Use it for endpoints that are not part of any contract (debug hooks, health probes).

Hiding a route only shapes the published documentation — the handler still serves traffic. It is NOT access control.

func Internal added in v0.1.1

func Internal() RouteOpt

Internal marks the route as internal: it is excluded from the generated OpenAPI document unless the mux was configured with WithInternal(true). When shown, the operation carries an "x-internal": true extension, which spec-filtering tools (e.g. Redocly) understand.

Like Hidden, this only shapes the published documentation — the handler still serves traffic in every environment. It is NOT access control.

func OperationID

func OperationID(id string) RouteOpt

OperationID sets the operationId. If not set, stdocs auto-derives one from the method and path.

func Optional

func Optional() RouteOpt

Optional marks the route's request body as not required. Only meaningful when called after WithBody.

func QueryParam

func QueryParam(name, typ, desc string) RouteOpt

QueryParam is shorthand for WithParam(name, "query", typ, desc).

func Summary

func Summary(s string) RouteOpt

Summary sets the route's summary (the short single-line description shown next to the operation in UIs).

func Tags

func Tags(names ...string) RouteOpt

Tags sets the route's tags. Multiple Tags calls accumulate.

func WithBody

func WithBody(body any) RouteOpt

WithBody sets the route's request body. body is a zero value of the type to reflect; its type is used to build the JSON Schema when the spec document is assembled. Struct fields may carry doc: (or description:) and example: tags, which become the field's schema description and example (examples are parsed according to the field type). The default content type is application/json (override with WithBodyContentType).

Mark the body as not required with Optional().

func WithBodyContentType

func WithBodyContentType(ct string) RouteOpt

WithBodyContentType sets the content type for the request body, creating the request-body entry if it does not exist yet. The default is "application/json". The order relative to WithBody does not matter.

stdocs.WithBody(MyRequest{}),
stdocs.WithBodyContentType("application/xml"),

func WithExample

func WithExample(value any) RouteOpt

WithExample adds an example value to the request body if one has been declared (via WithBody), otherwise to the most recently declared response (via WithResponse). If neither has been declared, WithExample is a no-op. To target a specific response regardless of declaration order, use WithResponseExample.

The value is encoded as JSON and stored under the OpenAPI "example" field of the media type object (content.<type>.example).

Example:

mux.HandleFunc("POST /users", createUser,
    stdocs.WithBody(CreateUserRequest{}),
    stdocs.WithResponse(201, User{}),
    stdocs.WithExample(CreateUserRequest{Title: "Buy milk"}),
)

Subsequent WithExample calls overwrite the previous example.

func WithNoSecurity

func WithNoSecurity() RouteOpt

WithNoSecurity opts the operation out of any security requirement. This emits an empty `security: []` array at the operation level, which the OpenAPI spec defines as overriding a globally-applied scheme. Without this (i.e. leaving Security empty), the operation inherits the global security requirement.

func WithParam

func WithParam(name, in, typ, description string) RouteOpt

WithParam adds a parameter to the route. in is one of "path", "query", "header", "cookie". typ is the JSON Schema type name ("string", "integer", "number", "boolean", "array"). For arrays, the items are also string-typed.

Multiple WithParam calls accumulate.

func WithResponse

func WithResponse(status int, body any) RouteOpt

WithResponse adds a response entry. body is a zero value whose type is reflected into a JSON Schema when the spec document is assembled (struct fields may carry doc:/description: and example: tags); pass nil if there is no body (e.g. 204 No Content). Pass status 0 to declare the OpenAPI "default" response — the catch-all entry consumers use for undeclared status codes, conventionally the shared error shape. Multiple WithResponse calls accumulate. Calling WithResponse twice for the same status replaces the body but keeps any description, headers, or example attached via the other response opts.

Example

Documenting request and response bodies through reflection.

package main

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/FumingPower3925/stdocs"
)

func main() {
	type User struct {
		ID   string `json:"id" doc:"Unique ID"`
		Name string `json:"name"`
	}
	type CreateUserRequest struct {
		Name string `json:"name"`
	}

	mux := stdocs.New(stdocs.WithTitle("My API"))
	mux.HandleFunc("POST /users", func(w http.ResponseWriter, r *http.Request) {},
		stdocs.Summary("Create a user"),
		stdocs.WithBody(CreateUserRequest{}),
		stdocs.WithResponse(201, User{}),
		stdocs.WithResponseDescription(201, "The newly created user"),
	)

	b, _ := mux.JSON()
	var doc struct {
		Components struct {
			Schemas map[string]json.RawMessage `json:"schemas"`
		} `json:"components"`
	}
	_ = json.Unmarshal(b, &doc)
	for name := range doc.Components.Schemas {
		if name == "User" {
			fmt.Println("components.schemas has User")
		}
	}
}
Output:
components.schemas has User

func WithResponseDescription

func WithResponseDescription(status int, description string) RouteOpt

WithResponseDescription sets a custom description for a response status, creating the response entry if it does not exist yet. The order relative to WithResponse does not matter.

stdocs.WithResponse(200, User{}),
stdocs.WithResponseDescription(200, "The user, or 404 if not found"),

func WithResponseExample

func WithResponseExample(status int, value any) RouteOpt

WithResponseExample attaches an example to a specific response status, creating the response entry if it does not exist yet. The order relative to WithResponse does not matter.

stdocs.WithResponse(200, User{}),
stdocs.WithResponseExample(200, User{ID: "u-1", Name: "Alice"}),

func WithResponseHeader

func WithResponseHeader(status int, name, typ, description string) RouteOpt

WithResponseHeader adds a header entry to a response status, creating the response entry if it does not exist yet. Useful for documenting rate-limit, pagination, or other custom headers. The order relative to WithResponse does not matter.

stdocs.WithResponse(200, User{}),
stdocs.WithResponseHeader(200, "X-RateLimit-Remaining", "integer", "Remaining quota"),

func WithSecurity

func WithSecurity(name string, scopes ...string) RouteOpt

WithSecurity requires the named security scheme on this operation. scopes are only meaningful for OAuth2 schemes; pass no scopes for non-OAuth schemes.

Use WithNoSecurity to opt out of a globally-applied scheme for one route.

Example:

mux.HandleFunc("GET /me", getUser,
    stdocs.WithSecurity("bearerAuth"),
)

mux.HandleFunc("POST /posts", createPost,
    stdocs.WithSecurity("oauth2Auth", "write:posts", "read:posts"),
)

type SecurityRequirement

type SecurityRequirement = spec.SecurityRequirement

SecurityRequirement is one entry of a "security" array: scheme name -> required scopes (empty for non-OAuth schemes).

type SecurityScheme

type SecurityScheme = spec.SecurityScheme

SecurityScheme describes one components.securitySchemes entry. Set Type plus the type-specific fields: Scheme/BearerFormat for http, In/Name for apiKey, Flows for oauth2, and OpenIDConnectURL for openIdConnect. Description is optional.

type SecuritySchemeType

type SecuritySchemeType = spec.SecuritySchemeType

SecuritySchemeType is the "type" of a security scheme: SecurityHTTP, SecurityAPIKey, SecurityOAuth2, or SecurityOpenIDConnect.

type Server

type Server = spec.Server

Server is one OpenAPI "servers" entry. Fields: URL, Description. Added via WithServer (the default relative "/" entry stays first).

type SpecInput

type SpecInput = spec.SpecInput

SpecInput is the input consumed by the internal emitters. Exposed for advanced use only.

type SpecVersion

type SpecVersion = version.SpecVersion

SpecVersion is the OpenAPI spec version ("3.0.4", "3.1.2", or "3.2.0"). Use the OpenAPI30 / OpenAPI31 / OpenAPI32 constants with WithVersion.

type TagDecl

type TagDecl = spec.TagDecl

TagDecl declares a top-level tag. Fields: Name, Description. Added via WithTag.

type Webhook

type Webhook = spec.Webhook

Webhook describes one OpenAPI 3.1/3.2 webhook. Fields: Method, Summary, Description, OperationID, RequestBody, Responses. Describe payloads by setting BodyValue on the request body or responses; schemas are reflected at document-build time.

Directories

Path Synopsis
cmd
demo command
Package main is a demo of stdocs using a fictional Task Tracker API.
Package main is a demo of stdocs using a fictional Task Tracker API.
internal
pattern
Package pattern parses Go 1.22+ net/http.ServeMux pattern strings.
Package pattern parses Go 1.22+ net/http.ServeMux pattern strings.
schema
Package schema reflects Go values into a version-agnostic JSON Schema representation consumed by the OpenAPI emitters in internal/spec.
Package schema reflects Go values into a version-agnostic JSON Schema representation consumed by the OpenAPI emitters in internal/spec.
spec
Package spec builds OpenAPI 3.0, 3.1, and 3.2 documents from internal *spec.SpecInput values.
Package spec builds OpenAPI 3.0, 3.1, and 3.2 documents from internal *spec.SpecInput values.
spec/yaml
Package yaml converts JSON documents (the form produced by the OpenAPI emitters) to YAML.
Package yaml converts JSON documents (the form produced by the OpenAPI emitters) to YAML.
version
Package version defines the OpenAPI spec-version identifiers used by the emitters.
Package version defines the OpenAPI spec-version identifiers used by the emitters.
ui
redoc
Package redoc provides a Redoc UI for stdocs.
Package redoc provides a Redoc UI for stdocs.
redocemb
Package redocemb provides an embedded (air-gapped) Redoc UI for stdocs.
Package redocemb provides an embedded (air-gapped) Redoc UI for stdocs.
scalar
Package scalar provides a Scalar UI for stdocs.
Package scalar provides a Scalar UI for stdocs.
scalaremb
Package scalaremb provides an embedded (air-gapped) Scalar UI for stdocs.
Package scalaremb provides an embedded (air-gapped) Scalar UI for stdocs.
stoplight
Package stoplight provides a Stoplight Elements UI for stdocs.
Package stoplight provides a Stoplight Elements UI for stdocs.
stoplightemb
Package stoplightemb provides an embedded (air-gapped) Stoplight Elements UI for stdocs.
Package stoplightemb provides an embedded (air-gapped) Stoplight Elements UI for stdocs.
swaggerui
Package swaggerui provides a Swagger UI for stdocs.
Package swaggerui provides a Swagger UI for stdocs.
swaggeruiemb
Package swaggeruiemb provides an embedded (air-gapped) Swagger UI for stdocs.
Package swaggeruiemb provides an embedded (air-gapped) Swagger UI for stdocs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL