mirror of
https://github.com/moby/moby.git
synced 2026-08-08 17:11:38 +00:00
483 lines
13 KiB
Go
483 lines
13 KiB
Go
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/go-openapi/runtime/server-middleware/docui"
|
|
"github.com/go-openapi/runtime/server-middleware/negotiate"
|
|
)
|
|
|
|
/////////////////////////////////////////////////////////:
|
|
// Seam to the negotiate options introduced in v0.29.5
|
|
/////////////////////////////////////////////////////////:
|
|
|
|
// NegotiateOption configures [NegotiateContentType] behaviour.
|
|
//
|
|
// Deprecated: moved to the [negotiate] package. Use [negotiate.Option] instead.
|
|
type NegotiateOption = negotiate.Option
|
|
|
|
// NegotiateContentType returns the best offered content type for the
|
|
// request's Accept header.
|
|
//
|
|
// Deprecated: moved to the [negotiate] package. Use [negotiate.ContentType] instead.
|
|
func NegotiateContentType(r *http.Request, offers []string, defaultOffer string, opts ...NegotiateOption) string {
|
|
return negotiate.ContentType(r, offers, defaultOffer, opts...)
|
|
}
|
|
|
|
// NegotiateContentEncoding returns the best offered content encoding for
|
|
// the request's Accept-Encoding header.
|
|
//
|
|
// Deprecated: moved to the [negotiate] package. Use [negotiate.ContentEncoding] instead.
|
|
func NegotiateContentEncoding(r *http.Request, offers []string) string {
|
|
return negotiate.ContentEncoding(r, offers)
|
|
}
|
|
|
|
// WithIgnoreParameters returns a [NegotiateOption] that strips MIME-type
|
|
// parameters from both Accept entries and offers before matching,
|
|
// restoring the pre-v0.30 behaviour.
|
|
//
|
|
// Deprecated: moved to the [negotiate] package. Use [negotiate.WithIgnoreParameters] instead.
|
|
func WithIgnoreParameters(ignore bool) NegotiateOption {
|
|
return negotiate.WithIgnoreParameters(ignore)
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////:
|
|
// Seam to the UI options
|
|
/////////////////////////////////////////////////////////:
|
|
|
|
// RapiDoc creates a [http.Handler] to serve a documentation site for a swagger spec.
|
|
//
|
|
// This allows for altering the spec before starting the [http] listener.
|
|
//
|
|
// Deprecated: moved to the [docui] package. Use [docui.RapiDoc] instead.
|
|
func RapiDoc(opts RapiDocOpts, next http.Handler) http.Handler {
|
|
return docui.RapiDoc(next, opts.toFuncOptions()...)
|
|
}
|
|
|
|
// Redoc creates a [http.Handler] to serve a documentation site for a swagger spec.
|
|
//
|
|
// This allows for altering the spec before starting the [http] listener.
|
|
//
|
|
// Deprecated: moved to the [docui] package. Use [docui.Redoc] instead.
|
|
func Redoc(opts RedocOpts, next http.Handler) http.Handler {
|
|
return docui.Redoc(next, opts.toFuncOptions()...)
|
|
}
|
|
|
|
// SwaggerUI creates a [http.Handler] to serve a documentation site for a swagger spec.
|
|
//
|
|
// This allows for altering the spec before starting the [http] listener.
|
|
//
|
|
// Deprecated: moved to the [docui] package. Use [docui.SwaggerUI] instead.
|
|
func SwaggerUI(opts SwaggerUIOpts, next http.Handler) http.Handler {
|
|
return docui.SwaggerUI(next, opts.toFuncOptions()...)
|
|
}
|
|
|
|
// SwaggerUIOAuth2Callback creates a middleware that serves the OAuth2 callback page used by Swagger UI.
|
|
//
|
|
// Deprecated: moved to the [docui] package. Use [docui.SwaggerUIOAuth2Callback] instead.
|
|
func SwaggerUIOAuth2Callback(opts SwaggerUIOpts, next http.Handler) http.Handler {
|
|
return docui.SwaggerUIOAuth2Callback(next, opts.toFuncOptions()...)
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////:
|
|
// Seam to the spec middleware options
|
|
/////////////////////////////////////////////////////////:
|
|
|
|
// SpecOption can be applied to the [Spec] serving [middleware].
|
|
//
|
|
// Deprecated: moved to the [docui] package. Use [docui.SpecOption] instead.
|
|
type SpecOption func(*specOptions)
|
|
|
|
type specOptions struct {
|
|
BasePath string
|
|
Path string
|
|
Document string
|
|
}
|
|
|
|
func (o specOptions) fullPath() string {
|
|
return path.Join(o.BasePath, o.Path, o.Document)
|
|
}
|
|
|
|
func specOptionsWithDefaults(basePath string, opts []SpecOption) specOptions {
|
|
o := specOptions{
|
|
BasePath: "/",
|
|
Path: "",
|
|
Document: "swagger.json",
|
|
}
|
|
|
|
for _, apply := range opts {
|
|
apply(&o)
|
|
}
|
|
if basePath != "" {
|
|
o.BasePath = basePath
|
|
}
|
|
|
|
return o
|
|
}
|
|
|
|
// Spec creates a [middleware] to serve a swagger spec as a JSON document.
|
|
//
|
|
// This allows for altering the spec before starting the [http] listener.
|
|
//
|
|
// The basePath argument indicates the path of the spec document (defaults to "/").
|
|
// Additional [SpecOption] can be used to change the name of the document (defaults to "swagger.json").
|
|
//
|
|
// Deprecated: moved to the [docui] package as [docui.ServeSpec].
|
|
func Spec(basePath string, spec []byte, next http.Handler, opts ...SpecOption) http.Handler {
|
|
o := specOptionsWithDefaults(basePath, opts)
|
|
|
|
return docui.ServeSpec(spec, next, docui.WithSpecPath(o.fullPath()))
|
|
|
|
}
|
|
|
|
// WithSpecPath sets the path to be joined to the base path of the
|
|
// spec-serving middleware (see [docui.ServeSpec]).
|
|
//
|
|
// This is empty by default.
|
|
func WithSpecPath(pth string) SpecOption {
|
|
return func(o *specOptions) {
|
|
o.Path = pth
|
|
}
|
|
}
|
|
|
|
// WithSpecDocument sets the name of the JSON document served as a spec.
|
|
//
|
|
// By default, this is "swagger.json".
|
|
func WithSpecDocument(doc string) SpecOption {
|
|
return func(o *specOptions) {
|
|
if doc == "" {
|
|
return
|
|
}
|
|
|
|
o.Document = doc
|
|
}
|
|
}
|
|
|
|
// UIOptions defines common options for UI serving middlewares.
|
|
//
|
|
// Deprecated: use instead the function options provided by [docui].
|
|
type UIOptions struct {
|
|
// 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.
|
|
//
|
|
// Defaults to: /swagger.json
|
|
SpecURL string
|
|
|
|
// Title for the documentation site, default to: API documentation
|
|
Title string
|
|
|
|
// Template specifies a custom template to serve the UI
|
|
Template string
|
|
}
|
|
|
|
// toFuncOptions bridges the deprecated options struct with the newer function options in [docui].
|
|
func (o UIOptions) toFuncOptions() []docui.Option {
|
|
const structMembers = 5
|
|
opts := make([]docui.Option, 0, structMembers)
|
|
|
|
if o.BasePath != "" {
|
|
opts = append(opts, docui.WithUIBasePath(o.BasePath))
|
|
}
|
|
|
|
if o.Path != "" {
|
|
opts = append(opts, docui.WithUIPath(o.Path))
|
|
}
|
|
|
|
if o.SpecURL != "" {
|
|
opts = append(opts, docui.WithSpecURL(o.SpecURL))
|
|
}
|
|
|
|
if o.Title != "" {
|
|
opts = append(opts, docui.WithUITitle(o.Title))
|
|
}
|
|
|
|
if o.Template != "" {
|
|
opts = append(opts, docui.WithUITemplate(o.Template))
|
|
}
|
|
|
|
return opts
|
|
}
|
|
|
|
// RapiDocOpts configures the [RapiDoc] middlewares.
|
|
//
|
|
// Deprecated: use instead the function options provided by [docui].
|
|
type RapiDocOpts struct {
|
|
// 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.
|
|
//
|
|
// Defaults to: /swagger.json
|
|
SpecURL string
|
|
|
|
// Title for the documentation site, default to: API documentation
|
|
Title string
|
|
|
|
// Template specifies a custom template to serve the UI
|
|
Template string
|
|
|
|
// RapiDocURL points to the js asset that generates the rapidoc site.
|
|
//
|
|
// Defaults to https://unpkg.com/rapidoc/dist/rapidoc-min.js
|
|
RapiDocURL string
|
|
}
|
|
|
|
func (o RapiDocOpts) toFuncOptions() []docui.Option {
|
|
const structMembers = 6
|
|
opts := make([]docui.Option, 0, structMembers)
|
|
|
|
if o.BasePath != "" {
|
|
opts = append(opts, docui.WithUIBasePath(o.BasePath))
|
|
}
|
|
|
|
if o.Path != "" {
|
|
opts = append(opts, docui.WithUIPath(o.Path))
|
|
}
|
|
|
|
if o.SpecURL != "" {
|
|
opts = append(opts, docui.WithSpecURL(o.SpecURL))
|
|
}
|
|
|
|
if o.Title != "" {
|
|
opts = append(opts, docui.WithUITitle(o.Title))
|
|
}
|
|
|
|
if o.Template != "" {
|
|
opts = append(opts, docui.WithUITemplate(o.Template))
|
|
}
|
|
|
|
if o.RapiDocURL != "" {
|
|
opts = append(opts, docui.WithUIAssetsURL(o.RapiDocURL))
|
|
}
|
|
|
|
return opts
|
|
}
|
|
|
|
// RedocOpts configures the [Redoc] middlewares.
|
|
//
|
|
// Deprecated: use instead the function options provided by [docui].
|
|
type RedocOpts struct {
|
|
// 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.
|
|
//
|
|
// Defaults to: /swagger.json
|
|
SpecURL string
|
|
|
|
// Title for the documentation site, default to: API documentation
|
|
Title string
|
|
|
|
// Template specifies a custom template to serve the UI
|
|
Template string
|
|
|
|
// RedocURL points to the js that generates the redoc site.
|
|
//
|
|
// Defaults to: https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js
|
|
RedocURL string
|
|
}
|
|
|
|
func (o RedocOpts) toFuncOptions() []docui.Option {
|
|
const structMembers = 6
|
|
opts := make([]docui.Option, 0, structMembers)
|
|
|
|
if o.BasePath != "" {
|
|
opts = append(opts, docui.WithUIBasePath(o.BasePath))
|
|
}
|
|
|
|
if o.Path != "" {
|
|
opts = append(opts, docui.WithUIPath(o.Path))
|
|
}
|
|
|
|
if o.SpecURL != "" {
|
|
opts = append(opts, docui.WithSpecURL(o.SpecURL))
|
|
}
|
|
|
|
if o.Title != "" {
|
|
opts = append(opts, docui.WithUITitle(o.Title))
|
|
}
|
|
|
|
if o.Template != "" {
|
|
opts = append(opts, docui.WithUITemplate(o.Template))
|
|
}
|
|
|
|
if o.RedocURL != "" {
|
|
opts = append(opts, docui.WithUIAssetsURL(o.RedocURL))
|
|
}
|
|
|
|
return opts
|
|
}
|
|
|
|
// SwaggerUIOpts configures the [SwaggerUI] [middleware].
|
|
//
|
|
// Deprecated: use instead the function options provided by [docui].
|
|
type SwaggerUIOpts struct {
|
|
// BasePath for the API, 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.
|
|
//
|
|
// Defaults to: /swagger.json
|
|
SpecURL string
|
|
|
|
// Title for the documentation site, default to: API documentation
|
|
Title string
|
|
|
|
// Template specifies a custom template to serve the UI
|
|
Template string
|
|
|
|
// OAuthCallbackURL the url called after OAuth2 login
|
|
//
|
|
// NOTE: in the new [docui.SwaggerUIOptions] type, this field is named `OAuth2CallbackURL`,
|
|
// which is more appropriate.
|
|
OAuthCallbackURL string
|
|
|
|
// The three components needed to embed swagger-ui
|
|
|
|
// SwaggerURL points to the js that generates the SwaggerUI site.
|
|
//
|
|
// Defaults to: https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js
|
|
SwaggerURL string
|
|
|
|
SwaggerPresetURL string
|
|
SwaggerStylesURL string
|
|
|
|
Favicon32 string
|
|
Favicon16 string
|
|
}
|
|
|
|
func (o SwaggerUIOpts) toFuncOptions() []docui.Option {
|
|
const structMembers = 6
|
|
opts := make([]docui.Option, 0, structMembers)
|
|
|
|
if o.BasePath != "" {
|
|
opts = append(opts, docui.WithUIBasePath(o.BasePath))
|
|
}
|
|
|
|
if o.Path != "" {
|
|
opts = append(opts, docui.WithUIPath(o.Path))
|
|
}
|
|
|
|
if o.SpecURL != "" {
|
|
opts = append(opts, docui.WithSpecURL(o.SpecURL))
|
|
}
|
|
|
|
if o.Title != "" {
|
|
opts = append(opts, docui.WithUITitle(o.Title))
|
|
}
|
|
|
|
if o.Template != "" {
|
|
opts = append(opts, docui.WithUITemplate(o.Template))
|
|
}
|
|
|
|
if o.SwaggerURL != "" {
|
|
opts = append(opts, docui.WithUIAssetsURL(o.SwaggerURL))
|
|
}
|
|
|
|
var empty SwaggerUIOpts
|
|
if o != empty {
|
|
swaggeruiOpts := docui.SwaggerUIOptions{
|
|
OAuth2CallbackURL: o.OAuthCallbackURL,
|
|
SwaggerPresetURL: o.SwaggerPresetURL,
|
|
SwaggerStylesURL: o.SwaggerStylesURL,
|
|
Favicon32: o.Favicon32,
|
|
Favicon16: o.Favicon16,
|
|
}
|
|
opts = append(opts, docui.WithSwaggerUIOptions(swaggeruiOpts))
|
|
}
|
|
|
|
return opts
|
|
}
|
|
|
|
// UIOption can be applied to UI serving [middleware] to alter the default
|
|
// behavior.
|
|
//
|
|
// Deprecated: use instead the function options provided by [docui].
|
|
type UIOption func(*UIOptions)
|
|
|
|
// uiOptionsWithDefaults applies the given options on top of an empty
|
|
// [UIOptions]. Per-flavor handlers ([SwaggerUI], [Redoc], [RapiDoc])
|
|
// fill in the remaining defaults via [UIOptions.EnsureDefaults] when
|
|
// the option struct is used.
|
|
func uiOptionsWithDefaults(opts []UIOption) UIOptions {
|
|
var o UIOptions
|
|
for _, apply := range opts {
|
|
apply(&o)
|
|
}
|
|
|
|
return o
|
|
}
|
|
|
|
// WithUIBasePath sets the base path from where to serve the UI assets.
|
|
//
|
|
// Deprecated: use instead the function options provided by [docui].
|
|
func WithUIBasePath(base string) UIOption {
|
|
return func(o *UIOptions) {
|
|
if !strings.HasPrefix(base, "/") {
|
|
base = "/" + base
|
|
}
|
|
o.BasePath = base
|
|
}
|
|
}
|
|
|
|
// WithUIPath sets the path from where to serve the UI assets (i.e. /{basepath}/{path}.
|
|
//
|
|
// Deprecated: use instead the function options provided by [docui].
|
|
func WithUIPath(pth string) UIOption {
|
|
return func(o *UIOptions) {
|
|
o.Path = pth
|
|
}
|
|
}
|
|
|
|
// WithUISpecURL sets the path from where to serve swagger spec document.
|
|
//
|
|
// This may be specified as a full URL or a path.
|
|
//
|
|
// By default, this is "/swagger.json".
|
|
//
|
|
// Deprecated: use instead the function options provided by [docui].
|
|
func WithUISpecURL(specURL string) UIOption {
|
|
return func(o *UIOptions) {
|
|
o.SpecURL = specURL
|
|
}
|
|
}
|
|
|
|
// WithUITitle sets the title of the UI.
|
|
//
|
|
// Deprecated: use instead the function options provided by [docui].
|
|
func WithUITitle(title string) UIOption {
|
|
return func(o *UIOptions) {
|
|
o.Title = title
|
|
}
|
|
}
|
|
|
|
// WithTemplate allows to set a custom template for the UI.
|
|
//
|
|
// UI [middleware] will panic if the template does not parse or execute properly.
|
|
//
|
|
// Deprecated: use instead the function options provided by [docui].
|
|
func WithTemplate(tpl string) UIOption {
|
|
return func(o *UIOptions) {
|
|
o.Template = tpl
|
|
}
|
|
}
|