Files
buildx/vendor/github.com/go-openapi/runtime/server-middleware/docui/options.go
T

254 lines
6.2 KiB
Go

// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
// SPDX-License-Identifier: Apache-2.0
package docui
import (
"net/http"
"net/url"
"strings"
)
const (
// constants that are common to all UI-serving middlewares.
defaultDocsPath = "docs"
defaultDocsURL = "/swagger.json"
defaultDocsTitle = "API Documentation"
contentTypeHeader = "Content-Type"
applicationJSON = "application/json"
)
// UIMiddleware is a function returning a http middleware which accepts UI [Option].
type UIMiddleware func(...Option) func(http.Handler) http.Handler
// Option to tune your swagger documentation UI middleware.
//
// Options may be combined to alter the route at which the UI asset is served,
// the URL of the spec document, the source URL of the UI asset and the title of the UI page.
//
// The embedded js scriptlet served may be modified using [WithUITemplate].
type Option func(*options)
// SpecOption can be applied to the [ServeSpec] middleware.
type SpecOption func(*specOptions)
// SwaggerUIOptions define a group of extra options specific to the SwaggerUI component.
type SwaggerUIOptions struct {
// OAuth2CallbackURL sets the URL called after OAuth2 login
OAuth2CallbackURL string
// Defines the URL of the swagger UI assets with presets.
//
// Default: https://unpkg.com/swagger-ui-dist/swagger-ui-standalone-preset.js
SwaggerPresetURL string
// Defines style sheet URL.
//
// Default: https://unpkg.com/swagger-ui-dist/swagger-ui.css
SwaggerStylesURL string
// Define the favicons URLs.
//
// Defaults:
//
// - 16x16: https://unpkg.com/swagger-ui-dist/favicon-16x16.png
// - 32x32: https://unpkg.com/swagger-ui-dist/favicon-32x32.png
Favicon32 string
Favicon16 string
}
func (o *SwaggerUIOptions) applySwaggerUIDefaults() {
if o.SwaggerPresetURL == "" {
o.SwaggerPresetURL = swaggerPresetLatest
}
if o.SwaggerStylesURL == "" {
o.SwaggerStylesURL = swaggerStylesLatest
}
if o.Favicon16 == "" || o.Favicon32 == "" {
o.Favicon16 = swaggerFavicon16Latest
o.Favicon32 = swaggerFavicon32Latest
}
}
type (
options struct {
SwaggerUIOptions
// BasePath for the UI, defaults to: /
BasePath string
// Path combines with BasePath to construct the path to the UI, defaults to: "docs".
Path string
// SpecURL is the URL of the spec document.
SpecURL string
// Title for the documentation site, default to: API documentation
Title string
// Template specifies a custom template to serve the UI
Template string
// AssetsURL points to the js asset that generates the documentation page.
AssetsURL string
}
specOptions struct {
Path string
Document string
}
)
////////////////////////////////////////////////////////////
// Common UI options
////////////////////////////////////////////////////////////
// WithUIBasePath sets the base path from where to serve the UI assets.
//
// Default: "/"
func WithUIBasePath(base string) Option {
return func(o *options) {
if !strings.HasPrefix(base, "/") {
base = "/" + base
}
o.BasePath = base
}
}
// WithUIPath sets the path from where to serve the UI assets (i.e. /{basepath}/{path}).
//
// Default: "docs"
func WithUIPath(pth string) Option {
return func(o *options) {
o.Path = pth
}
}
// WithUITitle sets the title of the UI.
//
// Default: "API documentation"
func WithUITitle(title string) Option {
return func(o *options) {
o.Title = title
}
}
// WithUIAssetsURL sets the URL from where to fetch the js assets.
//
// Defaults:
//
// - for Redoc: https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js
// - for RapiDoc, this defaults to: https://unpkg.com/rapidoc/dist/rapidoc-min.js
// - for SwaggerUI: https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js
func WithUIAssetsURL(assets string) Option {
return func(o *options) {
o.AssetsURL = assets
}
}
// WithUITemplate allows to set a custom template for the UI.
//
// This allows the caller to fully customize the rendered UI, using the advanced options
// provided by any UI.
//
// The UI [middleware] will panic if the template does not parse or execute properly.
//
// Reference documentations to customize your js scriptlet:
//
// - for Redoc: https://github.com/Redocly/redoc/blob/main/docs/deployment/html.md
// - for RapiDoc: https://github.com/rapi-doc/RapiDoc
// - for SwaggerUI: https://github.com/swagger-api/swagger-ui
func WithUITemplate[StringOrBytes ~string | ~[]byte](tpl StringOrBytes) Option {
return func(o *options) {
o.Template = string(tpl)
}
}
// WithSpecURL sets the URL of the spec document.
//
// Defaults to: /swagger.json
func WithSpecURL(u string) Option {
return func(o *options) {
o.SpecURL = u
}
}
////////////////////////////////////////////////////////////
// SwaggerUI UI options
////////////////////////////////////////////////////////////
func WithSwaggerUIOptions(opts SwaggerUIOptions) Option {
return func(o *options) {
o.SwaggerUIOptions = opts
}
}
////////////////////////////////////////////////////////////
// Spec options
////////////////////////////////////////////////////////////
// WithSpecPath sets the path of the spec document.
//
// This is "/swagger.json" by default.
func WithSpecPath(pth string) SpecOption {
return func(o *specOptions) {
if pth == "" {
return
}
o.Path = pth
}
}
// WithSpecPathFromOptions reuses the same SpecPath as the one specified in
// a set of UI [Option] (extract the path from the URL provided by [WithSpecURL]).
func WithSpecPathFromOptions(opts ...Option) SpecOption {
return func(o *specOptions) {
uiOpts := optionsWithDefaults(opts)
// If the spec URL is provided, there is a non-default path to serve the spec.
//
// This makes sure that the UI middleware is aligned with the Spec middleware.
u, _ := url.Parse(uiOpts.SpecURL)
if u.Path == "" {
return
}
o.Path = u.Path
}
}
func optionsWithDefaults(opts []Option, prepend ...Option) options {
o := options{
BasePath: "/",
Path: defaultDocsPath,
SpecURL: defaultDocsURL,
Title: defaultDocsTitle,
}
prepend = append(prepend, opts...)
for _, apply := range prepend {
apply(&o)
}
return o
}
func specOptionsWithDefaults(opts []SpecOption) specOptions {
o := specOptions{
Path: defaultDocsURL,
}
for _, apply := range opts {
apply(&o)
}
if !strings.HasPrefix(o.Path, "/") {
o.Path = "/" + o.Path
}
return o
}