AnnouncementsIntroducing Arkoren

    Menu

    Serving Documentation

    Export an HTTP contract, serve cached JSON, and mount a bundled Swagger UI with explicit access controls.

    What's on this page
    1. Export deterministic JSON as an artifact or serve a document cached on its first request.
    2. Mount bundled Swagger UI assets and choose safe base paths and document URLs.
    3. Protect the JSON contract and complete viewer subtree with explicit access and browser policies.
    On this page

    You can distribute your HTTP contract as a build artifact without exposing a documentation endpoint. If clients need live access, register a JSON handler; if people need a browser viewer, add Swagger UI separately. None of these choices starts a listener or installs authentication.

    The examples assume an annotated routes router, as introduced in the overview. Finish registration before exporting concurrently or serving requests.

    Export JSON

    For a contract test, client generator, or release artifact, export after registering the API routes:

    document, err := routes.OpenAPI("Greeting API", "1.0.0")

    On success, document holds OpenAPI 3.2.1 JSON bytes. Save them through your build’s artifact-writing step. Identical declarations and document settings produce identical bytes; no application startup, listener, or request is needed.

    Title and API version must be nonempty. Invalid declarations, duplicate operation IDs, and equivalent path templates return contextual errors instead of a partial document. Make export success a test or build requirement before publishing. This checks declarations, not whether handlers implement them, and it does not fill a live JSON handler’s cache.

    If you declared security requirements, include their schemes in the export callback. OpenAPIBuilder.Description can also set the document’s Info description; this does not replace operation descriptions.

    Serve JSON

    The JSON handler exposes endpoint names and schemas. If that information is private, register it on a protected router or restricted listener, not an unprotected public route. The handler adds no access controls.

    To publish the contract on an appropriately protected routes router:

    routes.Get("/openapi.json", routes.OpenAPIHandler("Greeting API", "1.0.0"))

    Serve that router through your HTTP server. A successful GET returns the document with Content-Type: application/json. The registration has no operation callback, so it is omitted from its own export.

    Document configuration callbacks run once when you construct OpenAPIHandler. Generation happens on its first request, capturing all routes registered before that request. The handler caches either the generated bytes or the generation error. Later registrations do not invalidate it; construct another handler when you need a different document. Construction does not compile or freeze the router.

    This is an in-process generation cache, not an HTTP cache policy. The JSON handler sets no Cache-Control header; configure that policy in your middleware if needed. A generation failure returns through the router’s ordinary error handling on every request to that handler, rather than retrying generation.

    Add Swagger UI

    Swagger UI lets people browse the document and make API requests from their browser. Protect its complete subtree as well as the JSON endpoint when the contract is private; protecting only the HTML page leaves the JSON exposed.

    Import arkoren.dev/core/http/swagger and construct a viewer for your JSON URL:

    viewer, err := swagger.Handler("/docs", "/openapi.json")

    Invalid paths or URLs return an error. After checking err, register both the base route and its subtree on the appropriately protected router:

    routes.Get("/docs", viewer)
    routes.Get("/docs/{path...}", viewer)

    The viewer serves /docs and /docs/, with assets beneath /docs/. Keep these paths equal to the base path passed to the factory. Leave both registrations unannotated: the exporter does not discover operations inside the UI, and an annotated catch-all would fail export.

    Once the server runs, opening /docs/ makes the browser fetch /openapi.json. The factory neither generates nor fetches that document. Pinned JavaScript and CSS are bundled locally; the initializer disables the remote validator and query-string configuration. The browser still needs access to the document and to any API it calls, so bundled assets do not make a remote API available offline.

    If the default tab title, API documentation, is too generic, use this alternative construction:

    viewer, err := swagger.Handler("/docs", "/openapi.json", func(page *swagger.Builder) {
    	page.Title("Greeting API")
    })

    The title is escaped as plain text; an empty title remains empty. Construction callbacks run once, synchronously in order, even for invalid configuration. Nil callbacks panic. Retaining the draft cannot change the completed handler, which supports concurrent requests.

    Choose URLs

    Prefer a root-relative document URL such as /openapi.json when the viewer and document share an origin. HTTP(S) and relative URLs are also accepted. Relative URLs resolve against the configured base path plus /, consistently whether the page was opened at /docs or /docs/; request Host and forwarding headers do not change that resolution.

    The base path must be a clean absolute URL path with unreserved ASCII segments. It cannot have a trailing slash unless it is /. Wildcards, escaped separators, and queries are invalid. The document URL must be nonempty and cannot contain credentials, fragments, scheme-relative URLs, whitespace, or backslashes.

    The viewer serves only its page and named assets; unknown paths return 404. It accepts GET and HEAD, with no response body for HEAD. Other methods return 405 with Allow: GET, HEAD if they reach the handler; router method matching can reject them first. HTML and the initializer use Cache-Control: no-store; pinned JavaScript and CSS use public, max-age=3600.

    Protect Documentation

    A private contract needs protection at every entry point: the JSON route, viewer page, and viewer subtree. Use your existing authentication middleware or a restricted listener. Hiding an operation from OpenAPI does not protect the live endpoint, and publishing its security requirement does not enforce it.

    The browser must authenticate its document fetch as well as API requests made from the viewer. Swagger UI does not bypass API authentication, authorization, CORS, or other middleware. If you choose a cross-origin document URL, the browser policy and authentication mechanism must permit that fetch.

    If you configure Content Security Policy, allow same-origin scripts, inline styles used by Swagger UI, and connections to the document and API origins. Allow data images if you use the UI’s embedded images. No inline script permission is required.

    Diagnostic route tools are a separate operator interface. They inspect registered routes; they do not mutate OpenAPI schemas or turn REST endpoints into MCP tools. Publishing a contract does not replace an MCP server.

    For document export and settings, see the router API reference. For viewer configuration, see the swagger API reference.

    Open a bulk documentation archive?

    This file contains every guide in its scope, not API declarations. Loading it all into an agent can exhaust its context window and increase processing time and cost. For coding tasks, start with the index and read only the relevant pages.

    Use the full archive for offline indexing, bulk processing, or deliberate large-context use.

    Browse the index instead
    Open archive