Skip to content

Limitations — what this does not do

transport-openapi mounts two routes and serves bytes. Most of what people expect of an "API docs system" is deliberately not here. This page is the list, so you can find out now rather than after you have designed around it.

It does not validate or parse your spec

Register takes []byte and serves them. It never unmarshals the document, so it cannot tell you that your OpenAPI is malformed, references a missing schema, or is not OpenAPI at all. An invalid document registers cleanly, serves 200, and fails in the browser when Stoplight tries to render it.

If you want the spec validated, validate it where it is generated — in the build, as a test — before it reaches Register.

It does not generate a spec

There is no reflection over your handlers and no route introspection. Something else produces openapi.yaml: a protobuf toolchain, a code generator, or a human. This module's job starts once you have the bytes.

The spec cannot be swapped at runtime

The spec slice is captured when Register is called and the docs page HTML is rendered once, at the same moment. There is no Reload, no watcher, and no way to replace either without building a new mux. A spec change ships as a new binary.

It only mounts on *http.ServeMux

The signature takes a concrete *http.ServeMux, not an interface and not http.Handler. Chi, Gin, Echo and the rest cannot be passed directly. Mount a ServeMux of your own inside whatever router you use and register on that.

The routes rely on net/http 1.22 method patterns (GET /path) and the {$} end-of-path wildcard, so the standard-library mux is not incidental — the routing shape is built on features only it has.

It does not serve docs cross-origin

There is no CORS support: no Access-Control-Allow-Origin, no preflight handling, and the try-it console is fixed at tryItCredentialsPolicy="same-origin". Hosting the docs page on a different origin from the API is outside what this module does — by design, not by omission.

It does not authenticate anything

Both routes are mounted open. If your API is private, your spec is a description of a private API and the console is a client for it — put authentication middleware in front of the docs paths yourself. Register has no option for it, and the security-header middleware it does apply is not access control.

It does not cache

Responses carry no Cache-Control, and the embedded assets carry no ETag or Last-Modified — the embedded filesystem has no modification times to report. Every uncached page load re-transfers the full 2.4 MB of Stoplight assets. Add caching in front if that matters.

The docs page is not themeable

Four things about the generated page are fixed in the template: hash routing, the sidebar layout, the same-origin credentials policy, and the markup itself. Only the <title> and the spec URL are configurable. There is no option to add a logo, a stylesheet, a favicon, or your own HTML around the console.

If you need a themed docs site, serve your own page and point it at /openapi.yaml — the spec route is useful on its own.

Stoplight Elements is pinned, and updating it is a release

The UI is Stoplight Elements v9.0.0, vendored under assets/ and compiled in. You cannot point the page at a newer Elements build, a CDN copy, or a different renderer such as Swagger UI or Redoc. Moving to a newer Elements version means a change and a release of this module.

Content-Type is always application/yaml

Even for a JSON spec. There is no negotiation and no option to override it. See the routes reference.

Bad paths panic rather than erroring

Register returns an error, but a malformed spec or docs path does not come back through it — it panics inside net/http while registering the pattern. The full list is in what happens when a path is wrong.