Update dependencies and tests
This commit updates the dependencies, vendor files and updates tests to take into account changes to the DB driver. Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
parent
069bdd8b6b
commit
97d03dd38d
693 changed files with 86307 additions and 28214 deletions
161
vendor/github.com/go-openapi/runtime/middleware/context.go
generated
vendored
161
vendor/github.com/go-openapi/runtime/middleware/context.go
generated
vendored
|
|
@ -18,6 +18,8 @@ import (
|
|||
stdContext "context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
|
|
@ -35,12 +37,21 @@ import (
|
|||
|
||||
// Debug when true turns on verbose logging
|
||||
var Debug = logger.DebugEnabled()
|
||||
|
||||
// Logger is the standard libray logger used for printing debug messages
|
||||
var Logger logger.Logger = logger.StandardLogger{}
|
||||
|
||||
func debugLog(format string, args ...interface{}) { //nolint:goprintffuncname
|
||||
if Debug {
|
||||
Logger.Printf(format, args...)
|
||||
func debugLogfFunc(lg logger.Logger) func(string, ...any) {
|
||||
if logger.DebugEnabled() {
|
||||
if lg == nil {
|
||||
return Logger.Debugf
|
||||
}
|
||||
|
||||
return lg.Debugf
|
||||
}
|
||||
|
||||
// muted logger
|
||||
return func(_ string, _ ...any) {}
|
||||
}
|
||||
|
||||
// A Builder can create middlewares
|
||||
|
|
@ -73,10 +84,11 @@ func (fn ResponderFunc) WriteResponse(rw http.ResponseWriter, pr runtime.Produce
|
|||
// used throughout to store request context with the standard context attached
|
||||
// to the http.Request
|
||||
type Context struct {
|
||||
spec *loads.Document
|
||||
analyzer *analysis.Spec
|
||||
api RoutableAPI
|
||||
router Router
|
||||
spec *loads.Document
|
||||
analyzer *analysis.Spec
|
||||
api RoutableAPI
|
||||
router Router
|
||||
debugLogf func(string, ...any) // a logging function to debug context and all components using it
|
||||
}
|
||||
|
||||
type routableUntypedAPI struct {
|
||||
|
|
@ -189,7 +201,9 @@ func (r *routableUntypedAPI) DefaultConsumes() string {
|
|||
return r.defaultConsumes
|
||||
}
|
||||
|
||||
// NewRoutableContext creates a new context for a routable API
|
||||
// NewRoutableContext creates a new context for a routable API.
|
||||
//
|
||||
// If a nil Router is provided, the DefaultRouter (denco-based) will be used.
|
||||
func NewRoutableContext(spec *loads.Document, routableAPI RoutableAPI, routes Router) *Context {
|
||||
var an *analysis.Spec
|
||||
if spec != nil {
|
||||
|
|
@ -199,26 +213,40 @@ func NewRoutableContext(spec *loads.Document, routableAPI RoutableAPI, routes Ro
|
|||
return NewRoutableContextWithAnalyzedSpec(spec, an, routableAPI, routes)
|
||||
}
|
||||
|
||||
// NewRoutableContextWithAnalyzedSpec is like NewRoutableContext but takes in input the analysed spec too
|
||||
// NewRoutableContextWithAnalyzedSpec is like NewRoutableContext but takes as input an already analysed spec.
|
||||
//
|
||||
// If a nil Router is provided, the DefaultRouter (denco-based) will be used.
|
||||
func NewRoutableContextWithAnalyzedSpec(spec *loads.Document, an *analysis.Spec, routableAPI RoutableAPI, routes Router) *Context {
|
||||
// Either there are no spec doc and analysis, or both of them.
|
||||
if !((spec == nil && an == nil) || (spec != nil && an != nil)) {
|
||||
panic(errors.New(http.StatusInternalServerError, "routable context requires either both spec doc and analysis, or none of them"))
|
||||
}
|
||||
|
||||
ctx := &Context{spec: spec, api: routableAPI, analyzer: an, router: routes}
|
||||
return ctx
|
||||
return &Context{
|
||||
spec: spec,
|
||||
api: routableAPI,
|
||||
analyzer: an,
|
||||
router: routes,
|
||||
debugLogf: debugLogfFunc(nil),
|
||||
}
|
||||
}
|
||||
|
||||
// NewContext creates a new context wrapper
|
||||
// NewContext creates a new context wrapper.
|
||||
//
|
||||
// If a nil Router is provided, the DefaultRouter (denco-based) will be used.
|
||||
func NewContext(spec *loads.Document, api *untyped.API, routes Router) *Context {
|
||||
var an *analysis.Spec
|
||||
if spec != nil {
|
||||
an = analysis.New(spec.Spec())
|
||||
}
|
||||
ctx := &Context{spec: spec, analyzer: an}
|
||||
ctx := &Context{
|
||||
spec: spec,
|
||||
analyzer: an,
|
||||
router: routes,
|
||||
debugLogf: debugLogfFunc(nil),
|
||||
}
|
||||
ctx.api = newRoutableUntypedAPI(spec, api, ctx)
|
||||
ctx.router = routes
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
|
|
@ -282,6 +310,13 @@ func (c *Context) BasePath() string {
|
|||
return c.spec.BasePath()
|
||||
}
|
||||
|
||||
// SetLogger allows for injecting a logger to catch debug entries.
|
||||
//
|
||||
// The logger is enabled in DEBUG mode only.
|
||||
func (c *Context) SetLogger(lg logger.Logger) {
|
||||
c.debugLogf = debugLogfFunc(lg)
|
||||
}
|
||||
|
||||
// RequiredProduces returns the accepted content types for responses
|
||||
func (c *Context) RequiredProduces() []string {
|
||||
return c.analyzer.RequiredProduces()
|
||||
|
|
@ -299,6 +334,7 @@ func (c *Context) BindValidRequest(request *http.Request, route *MatchedRoute, b
|
|||
if err != nil {
|
||||
res = append(res, err)
|
||||
} else {
|
||||
c.debugLogf("validating content type for %q against [%s]", ct, strings.Join(route.Consumes, ", "))
|
||||
if err := validateContentType(route.Consumes, ct); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
|
@ -397,16 +433,16 @@ func (c *Context) ResponseFormat(r *http.Request, offers []string) (string, *htt
|
|||
var rCtx = r.Context()
|
||||
|
||||
if v, ok := rCtx.Value(ctxResponseFormat).(string); ok {
|
||||
debugLog("[%s %s] found response format %q in context", r.Method, r.URL.Path, v)
|
||||
c.debugLogf("[%s %s] found response format %q in context", r.Method, r.URL.Path, v)
|
||||
return v, r
|
||||
}
|
||||
|
||||
format := NegotiateContentType(r, offers, "")
|
||||
if format != "" {
|
||||
debugLog("[%s %s] set response format %q in context", r.Method, r.URL.Path, format)
|
||||
c.debugLogf("[%s %s] set response format %q in context", r.Method, r.URL.Path, format)
|
||||
r = r.WithContext(stdContext.WithValue(rCtx, ctxResponseFormat, format))
|
||||
}
|
||||
debugLog("[%s %s] negotiated response format %q", r.Method, r.URL.Path, format)
|
||||
c.debugLogf("[%s %s] negotiated response format %q", r.Method, r.URL.Path, format)
|
||||
return format, r
|
||||
}
|
||||
|
||||
|
|
@ -469,7 +505,7 @@ func (c *Context) BindAndValidate(request *http.Request, matched *MatchedRoute)
|
|||
var rCtx = request.Context()
|
||||
|
||||
if v, ok := rCtx.Value(ctxBoundParams).(*validation); ok {
|
||||
debugLog("got cached validation (valid: %t)", len(v.result) == 0)
|
||||
c.debugLogf("got cached validation (valid: %t)", len(v.result) == 0)
|
||||
if len(v.result) > 0 {
|
||||
return v.bound, request, errors.CompositeValidationError(v.result...)
|
||||
}
|
||||
|
|
@ -481,7 +517,7 @@ func (c *Context) BindAndValidate(request *http.Request, matched *MatchedRoute)
|
|||
if len(result.result) > 0 {
|
||||
return result.bound, request, errors.CompositeValidationError(result.result...)
|
||||
}
|
||||
debugLog("no validation errors found")
|
||||
c.debugLogf("no validation errors found")
|
||||
return result.bound, request, nil
|
||||
}
|
||||
|
||||
|
|
@ -492,7 +528,7 @@ func (c *Context) NotFound(rw http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// Respond renders the response after doing some content negotiation
|
||||
func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []string, route *MatchedRoute, data interface{}) {
|
||||
debugLog("responding to %s %s with produces: %v", r.Method, r.URL.Path, produces)
|
||||
c.debugLogf("responding to %s %s with produces: %v", r.Method, r.URL.Path, produces)
|
||||
offers := []string{}
|
||||
for _, mt := range produces {
|
||||
if mt != c.api.DefaultProduces() {
|
||||
|
|
@ -501,7 +537,7 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
|
|||
}
|
||||
// the default producer is last so more specific producers take precedence
|
||||
offers = append(offers, c.api.DefaultProduces())
|
||||
debugLog("offers: %v", offers)
|
||||
c.debugLogf("offers: %v", offers)
|
||||
|
||||
var format string
|
||||
format, r = c.ResponseFormat(r, offers)
|
||||
|
|
@ -584,45 +620,92 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
|
|||
c.api.ServeErrorFor(route.Operation.ID)(rw, r, errors.New(http.StatusInternalServerError, "can't produce response"))
|
||||
}
|
||||
|
||||
func (c *Context) APIHandlerSwaggerUI(builder Builder) http.Handler {
|
||||
// APIHandlerSwaggerUI returns a handler to serve the API.
|
||||
//
|
||||
// This handler includes a swagger spec, router and the contract defined in the swagger spec.
|
||||
//
|
||||
// A spec UI (SwaggerUI) is served at {API base path}/docs and the spec document at /swagger.json
|
||||
// (these can be modified with uiOptions).
|
||||
func (c *Context) APIHandlerSwaggerUI(builder Builder, opts ...UIOption) http.Handler {
|
||||
b := builder
|
||||
if b == nil {
|
||||
b = PassthroughBuilder
|
||||
}
|
||||
|
||||
var title string
|
||||
sp := c.spec.Spec()
|
||||
if sp != nil && sp.Info != nil && sp.Info.Title != "" {
|
||||
title = sp.Info.Title
|
||||
}
|
||||
specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts)
|
||||
var swaggerUIOpts SwaggerUIOpts
|
||||
fromCommonToAnyOptions(uiOpts, &swaggerUIOpts)
|
||||
|
||||
swaggerUIOpts := SwaggerUIOpts{
|
||||
BasePath: c.BasePath(),
|
||||
Title: title,
|
||||
}
|
||||
|
||||
return Spec("", c.spec.Raw(), SwaggerUI(swaggerUIOpts, c.RoutesHandler(b)))
|
||||
return Spec(specPath, c.spec.Raw(), SwaggerUI(swaggerUIOpts, c.RoutesHandler(b)), specOpts...)
|
||||
}
|
||||
|
||||
// APIHandler returns a handler to serve the API, this includes a swagger spec, router and the contract defined in the swagger spec
|
||||
func (c *Context) APIHandler(builder Builder) http.Handler {
|
||||
// APIHandlerRapiDoc returns a handler to serve the API.
|
||||
//
|
||||
// This handler includes a swagger spec, router and the contract defined in the swagger spec.
|
||||
//
|
||||
// A spec UI (RapiDoc) is served at {API base path}/docs and the spec document at /swagger.json
|
||||
// (these can be modified with uiOptions).
|
||||
func (c *Context) APIHandlerRapiDoc(builder Builder, opts ...UIOption) http.Handler {
|
||||
b := builder
|
||||
if b == nil {
|
||||
b = PassthroughBuilder
|
||||
}
|
||||
|
||||
specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts)
|
||||
var rapidocUIOpts RapiDocOpts
|
||||
fromCommonToAnyOptions(uiOpts, &rapidocUIOpts)
|
||||
|
||||
return Spec(specPath, c.spec.Raw(), RapiDoc(rapidocUIOpts, c.RoutesHandler(b)), specOpts...)
|
||||
}
|
||||
|
||||
// APIHandler returns a handler to serve the API.
|
||||
//
|
||||
// This handler includes a swagger spec, router and the contract defined in the swagger spec.
|
||||
//
|
||||
// A spec UI (Redoc) is served at {API base path}/docs and the spec document at /swagger.json
|
||||
// (these can be modified with uiOptions).
|
||||
func (c *Context) APIHandler(builder Builder, opts ...UIOption) http.Handler {
|
||||
b := builder
|
||||
if b == nil {
|
||||
b = PassthroughBuilder
|
||||
}
|
||||
|
||||
specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts)
|
||||
var redocOpts RedocOpts
|
||||
fromCommonToAnyOptions(uiOpts, &redocOpts)
|
||||
|
||||
return Spec(specPath, c.spec.Raw(), Redoc(redocOpts, c.RoutesHandler(b)), specOpts...)
|
||||
}
|
||||
|
||||
func (c Context) uiOptionsForHandler(opts []UIOption) (string, uiOptions, []SpecOption) {
|
||||
var title string
|
||||
sp := c.spec.Spec()
|
||||
if sp != nil && sp.Info != nil && sp.Info.Title != "" {
|
||||
title = sp.Info.Title
|
||||
}
|
||||
|
||||
redocOpts := RedocOpts{
|
||||
BasePath: c.BasePath(),
|
||||
Title: title,
|
||||
// default options (may be overridden)
|
||||
optsForContext := []UIOption{
|
||||
WithUIBasePath(c.BasePath()),
|
||||
WithUITitle(title),
|
||||
}
|
||||
optsForContext = append(optsForContext, opts...)
|
||||
uiOpts := uiOptionsWithDefaults(optsForContext)
|
||||
|
||||
// If 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)
|
||||
var specPath string
|
||||
if u != nil {
|
||||
specPath = u.Path
|
||||
}
|
||||
|
||||
return Spec("", c.spec.Raw(), Redoc(redocOpts, c.RoutesHandler(b)))
|
||||
pth, doc := path.Split(specPath)
|
||||
if pth == "." {
|
||||
pth = ""
|
||||
}
|
||||
|
||||
return pth, uiOpts, []SpecOption{WithSpecDocument(doc)}
|
||||
}
|
||||
|
||||
// RoutesHandler returns a handler to serve the API, just the routes and the contract defined in the swagger spec
|
||||
|
|
|
|||
30
vendor/github.com/go-openapi/runtime/middleware/denco/router.go
generated
vendored
30
vendor/github.com/go-openapi/runtime/middleware/denco/router.go
generated
vendored
|
|
@ -2,6 +2,7 @@
|
|||
package denco
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
|
@ -29,13 +30,13 @@ const (
|
|||
|
||||
// Router represents a URL router.
|
||||
type Router struct {
|
||||
param *doubleArray
|
||||
// SizeHint expects the maximum number of path parameters in records to Build.
|
||||
// SizeHint will be used to determine the capacity of the memory to allocate.
|
||||
// By default, SizeHint will be determined from given records to Build.
|
||||
SizeHint int
|
||||
|
||||
static map[string]interface{}
|
||||
param *doubleArray
|
||||
}
|
||||
|
||||
// New returns a new Router.
|
||||
|
|
@ -71,7 +72,7 @@ func (rt *Router) Lookup(path string) (data interface{}, params Params, found bo
|
|||
func (rt *Router) Build(records []Record) error {
|
||||
statics, params := makeRecords(records)
|
||||
if len(params) > MaxSize {
|
||||
return fmt.Errorf("denco: too many records")
|
||||
return errors.New("denco: too many records")
|
||||
}
|
||||
if rt.SizeHint < 0 {
|
||||
rt.SizeHint = 0
|
||||
|
|
@ -197,24 +198,29 @@ func (da *doubleArray) lookup(path string, params []Param, idx int) (*node, []Pa
|
|||
if next := nextIndex(da.bc[idx].Base(), TerminationCharacter); next < len(da.bc) && da.bc[next].Check() == TerminationCharacter {
|
||||
return da.node[da.bc[next].Base()], params, true
|
||||
}
|
||||
|
||||
BACKTRACKING:
|
||||
for j := len(indices) - 1; j >= 0; j-- {
|
||||
i, idx := int(indices[j]>>32), int(indices[j]&0xffffffff)
|
||||
if da.bc[idx].IsSingleParam() {
|
||||
idx := nextIndex(da.bc[idx].Base(), ParamCharacter) //nolint:govet
|
||||
if idx >= len(da.bc) {
|
||||
nextIdx := nextIndex(da.bc[idx].Base(), ParamCharacter)
|
||||
if nextIdx >= len(da.bc) {
|
||||
break
|
||||
}
|
||||
|
||||
next := NextSeparator(path, i)
|
||||
params := append(params, Param{Value: path[i:next]}) //nolint:govet
|
||||
if nd, params, found := da.lookup(path[next:], params, idx); found { //nolint:govet
|
||||
return nd, params, true
|
||||
nextParams := params
|
||||
nextParams = append(nextParams, Param{Value: path[i:next]})
|
||||
if nd, nextNextParams, found := da.lookup(path[next:], nextParams, nextIdx); found {
|
||||
return nd, nextNextParams, true
|
||||
}
|
||||
}
|
||||
|
||||
if da.bc[idx].IsWildcardParam() {
|
||||
idx := nextIndex(da.bc[idx].Base(), WildcardCharacter) //nolint:govet
|
||||
params := append(params, Param{Value: path[i:]}) //nolint:govet
|
||||
return da.node[da.bc[idx].Base()], params, true
|
||||
nextIdx := nextIndex(da.bc[idx].Base(), WildcardCharacter)
|
||||
nextParams := params
|
||||
nextParams = append(nextParams, Param{Value: path[i:]})
|
||||
return da.node[da.bc[nextIdx].Base()], nextParams, true
|
||||
}
|
||||
}
|
||||
return nil, nil, false
|
||||
|
|
@ -326,7 +332,7 @@ func (da *doubleArray) arrange(records []*record, idx, depth int, usedBase map[i
|
|||
}
|
||||
base = da.findBase(siblings, idx, usedBase)
|
||||
if base > MaxSize {
|
||||
return -1, nil, nil, fmt.Errorf("denco: too many elements of internal slice")
|
||||
return -1, nil, nil, errors.New("denco: too many elements of internal slice")
|
||||
}
|
||||
da.setBase(idx, base)
|
||||
return base, siblings, leaf, err
|
||||
|
|
@ -387,7 +393,7 @@ func makeSiblings(records []*record, depth int) (sib []sibling, leaf *record, er
|
|||
case pc == c:
|
||||
continue
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("denco: BUG: routing table hasn't been sorted")
|
||||
return nil, nil, errors.New("denco: BUG: routing table hasn't been sorted")
|
||||
}
|
||||
if n > 0 {
|
||||
sib[n-1].end = i
|
||||
|
|
|
|||
10
vendor/github.com/go-openapi/runtime/middleware/go18.go
generated
vendored
10
vendor/github.com/go-openapi/runtime/middleware/go18.go
generated
vendored
|
|
@ -1,10 +0,0 @@
|
|||
//go:build go1.8
|
||||
// +build go1.8
|
||||
|
||||
package middleware
|
||||
|
||||
import "net/url"
|
||||
|
||||
func pathUnescape(path string) (string, error) {
|
||||
return url.PathUnescape(path)
|
||||
}
|
||||
9
vendor/github.com/go-openapi/runtime/middleware/pre_go18.go
generated
vendored
9
vendor/github.com/go-openapi/runtime/middleware/pre_go18.go
generated
vendored
|
|
@ -1,9 +0,0 @@
|
|||
// +build !go1.8
|
||||
|
||||
package middleware
|
||||
|
||||
import "net/url"
|
||||
|
||||
func pathUnescape(path string) (string, error) {
|
||||
return url.QueryUnescape(path)
|
||||
}
|
||||
70
vendor/github.com/go-openapi/runtime/middleware/rapidoc.go
generated
vendored
70
vendor/github.com/go-openapi/runtime/middleware/rapidoc.go
generated
vendored
|
|
@ -1,4 +1,3 @@
|
|||
//nolint:dupl
|
||||
package middleware
|
||||
|
||||
import (
|
||||
|
|
@ -11,66 +10,57 @@ import (
|
|||
|
||||
// RapiDocOpts configures the RapiDoc middlewares
|
||||
type RapiDocOpts struct {
|
||||
// BasePath for the UI path, defaults to: /
|
||||
// BasePath for the UI, defaults to: /
|
||||
BasePath string
|
||||
// Path combines with BasePath for the full UI path, defaults to: docs
|
||||
|
||||
// Path combines with BasePath to construct the path to the UI, defaults to: "docs".
|
||||
Path string
|
||||
// SpecURL the url to find the spec for
|
||||
|
||||
// SpecURL is the URL of the spec document.
|
||||
//
|
||||
// Defaults to: /swagger.json
|
||||
SpecURL string
|
||||
// RapiDocURL for the js that generates the rapidoc site, defaults to: https://cdn.jsdelivr.net/npm/rapidoc/bundles/rapidoc.standalone.js
|
||||
RapiDocURL 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
|
||||
}
|
||||
|
||||
// EnsureDefaults in case some options are missing
|
||||
func (r *RapiDocOpts) EnsureDefaults() {
|
||||
if r.BasePath == "" {
|
||||
r.BasePath = "/"
|
||||
}
|
||||
if r.Path == "" {
|
||||
r.Path = defaultDocsPath
|
||||
}
|
||||
if r.SpecURL == "" {
|
||||
r.SpecURL = defaultDocsURL
|
||||
}
|
||||
common := toCommonUIOptions(r)
|
||||
common.EnsureDefaults()
|
||||
fromCommonToAnyOptions(common, r)
|
||||
|
||||
// rapidoc-specifics
|
||||
if r.RapiDocURL == "" {
|
||||
r.RapiDocURL = rapidocLatest
|
||||
}
|
||||
if r.Title == "" {
|
||||
r.Title = defaultDocsTitle
|
||||
if r.Template == "" {
|
||||
r.Template = rapidocTemplate
|
||||
}
|
||||
}
|
||||
|
||||
// RapiDoc creates a middleware to serve a documentation site for a swagger spec.
|
||||
//
|
||||
// This allows for altering the spec before starting the http listener.
|
||||
func RapiDoc(opts RapiDocOpts, next http.Handler) http.Handler {
|
||||
opts.EnsureDefaults()
|
||||
|
||||
pth := path.Join(opts.BasePath, opts.Path)
|
||||
tmpl := template.Must(template.New("rapidoc").Parse(rapidocTemplate))
|
||||
tmpl := template.Must(template.New("rapidoc").Parse(opts.Template))
|
||||
assets := bytes.NewBuffer(nil)
|
||||
if err := tmpl.Execute(assets, opts); err != nil {
|
||||
panic(fmt.Errorf("cannot execute template: %w", err))
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
_ = tmpl.Execute(buf, opts)
|
||||
b := buf.Bytes()
|
||||
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == pth {
|
||||
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
|
||||
_, _ = rw.Write(b)
|
||||
return
|
||||
}
|
||||
|
||||
if next == nil {
|
||||
rw.Header().Set("Content-Type", "text/plain")
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
_, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(rw, r)
|
||||
})
|
||||
return serveUI(pth, assets.Bytes(), next)
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
|
|||
69
vendor/github.com/go-openapi/runtime/middleware/redoc.go
generated
vendored
69
vendor/github.com/go-openapi/runtime/middleware/redoc.go
generated
vendored
|
|
@ -1,4 +1,3 @@
|
|||
//nolint:dupl
|
||||
package middleware
|
||||
|
||||
import (
|
||||
|
|
@ -11,66 +10,58 @@ import (
|
|||
|
||||
// RedocOpts configures the Redoc middlewares
|
||||
type RedocOpts struct {
|
||||
// BasePath for the UI path, defaults to: /
|
||||
// BasePath for the UI, defaults to: /
|
||||
BasePath string
|
||||
// Path combines with BasePath for the full UI path, defaults to: docs
|
||||
|
||||
// Path combines with BasePath to construct the path to the UI, defaults to: "docs".
|
||||
Path string
|
||||
// SpecURL the url to find the spec for
|
||||
|
||||
// SpecURL is the URL of the spec document.
|
||||
//
|
||||
// Defaults to: /swagger.json
|
||||
SpecURL string
|
||||
// RedocURL for the js that generates the redoc site, defaults to: https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js
|
||||
RedocURL 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
|
||||
}
|
||||
|
||||
// EnsureDefaults in case some options are missing
|
||||
func (r *RedocOpts) EnsureDefaults() {
|
||||
if r.BasePath == "" {
|
||||
r.BasePath = "/"
|
||||
}
|
||||
if r.Path == "" {
|
||||
r.Path = defaultDocsPath
|
||||
}
|
||||
if r.SpecURL == "" {
|
||||
r.SpecURL = defaultDocsURL
|
||||
}
|
||||
common := toCommonUIOptions(r)
|
||||
common.EnsureDefaults()
|
||||
fromCommonToAnyOptions(common, r)
|
||||
|
||||
// redoc-specifics
|
||||
if r.RedocURL == "" {
|
||||
r.RedocURL = redocLatest
|
||||
}
|
||||
if r.Title == "" {
|
||||
r.Title = defaultDocsTitle
|
||||
if r.Template == "" {
|
||||
r.Template = redocTemplate
|
||||
}
|
||||
}
|
||||
|
||||
// Redoc creates a middleware to serve a documentation site for a swagger spec.
|
||||
//
|
||||
// This allows for altering the spec before starting the http listener.
|
||||
func Redoc(opts RedocOpts, next http.Handler) http.Handler {
|
||||
opts.EnsureDefaults()
|
||||
|
||||
pth := path.Join(opts.BasePath, opts.Path)
|
||||
tmpl := template.Must(template.New("redoc").Parse(redocTemplate))
|
||||
tmpl := template.Must(template.New("redoc").Parse(opts.Template))
|
||||
assets := bytes.NewBuffer(nil)
|
||||
if err := tmpl.Execute(assets, opts); err != nil {
|
||||
panic(fmt.Errorf("cannot execute template: %w", err))
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
_ = tmpl.Execute(buf, opts)
|
||||
b := buf.Bytes()
|
||||
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == pth {
|
||||
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
|
||||
_, _ = rw.Write(b)
|
||||
return
|
||||
}
|
||||
|
||||
if next == nil {
|
||||
rw.Header().Set("Content-Type", "text/plain")
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
_, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(rw, r)
|
||||
})
|
||||
return serveUI(pth, assets.Bytes(), next)
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
|
|||
21
vendor/github.com/go-openapi/runtime/middleware/request.go
generated
vendored
21
vendor/github.com/go-openapi/runtime/middleware/request.go
generated
vendored
|
|
@ -19,10 +19,10 @@ import (
|
|||
"reflect"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/logger"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
)
|
||||
|
||||
// UntypedRequestBinder binds and validates the data from a http request
|
||||
|
|
@ -31,6 +31,7 @@ type UntypedRequestBinder struct {
|
|||
Parameters map[string]spec.Parameter
|
||||
Formats strfmt.Registry
|
||||
paramBinders map[string]*untypedParamBinder
|
||||
debugLogf func(string, ...any) // a logging function to debug context and all components using it
|
||||
}
|
||||
|
||||
// NewUntypedRequestBinder creates a new binder for reading a request.
|
||||
|
|
@ -44,6 +45,7 @@ func NewUntypedRequestBinder(parameters map[string]spec.Parameter, spec *spec.Sw
|
|||
paramBinders: binders,
|
||||
Spec: spec,
|
||||
Formats: formats,
|
||||
debugLogf: debugLogfFunc(nil),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -52,10 +54,10 @@ func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RoutePara
|
|||
val := reflect.Indirect(reflect.ValueOf(data))
|
||||
isMap := val.Kind() == reflect.Map
|
||||
var result []error
|
||||
debugLog("binding %d parameters for %s %s", len(o.Parameters), request.Method, request.URL.EscapedPath())
|
||||
o.debugLogf("binding %d parameters for %s %s", len(o.Parameters), request.Method, request.URL.EscapedPath())
|
||||
for fieldName, param := range o.Parameters {
|
||||
binder := o.paramBinders[fieldName]
|
||||
debugLog("binding parameter %s for %s %s", fieldName, request.Method, request.URL.EscapedPath())
|
||||
o.debugLogf("binding parameter %s for %s %s", fieldName, request.Method, request.URL.EscapedPath())
|
||||
var target reflect.Value
|
||||
if !isMap {
|
||||
binder.Name = fieldName
|
||||
|
|
@ -102,3 +104,14 @@ func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RoutePara
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetLogger allows for injecting a logger to catch debug entries.
|
||||
//
|
||||
// The logger is enabled in DEBUG mode only.
|
||||
func (o *UntypedRequestBinder) SetLogger(lg logger.Logger) {
|
||||
o.debugLogf = debugLogfFunc(lg)
|
||||
}
|
||||
|
||||
func (o *UntypedRequestBinder) setDebugLogf(fn func(string, ...any)) {
|
||||
o.debugLogf = fn
|
||||
}
|
||||
|
|
|
|||
103
vendor/github.com/go-openapi/runtime/middleware/router.go
generated
vendored
103
vendor/github.com/go-openapi/runtime/middleware/router.go
generated
vendored
|
|
@ -17,10 +17,12 @@ package middleware
|
|||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
fpath "path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/runtime/logger"
|
||||
"github.com/go-openapi/runtime/security"
|
||||
"github.com/go-openapi/swag"
|
||||
|
||||
|
|
@ -67,10 +69,10 @@ func (r RouteParams) GetOK(name string) ([]string, bool, bool) {
|
|||
return nil, false, false
|
||||
}
|
||||
|
||||
// NewRouter creates a new context aware router middleware
|
||||
// NewRouter creates a new context-aware router middleware
|
||||
func NewRouter(ctx *Context, next http.Handler) http.Handler {
|
||||
if ctx.router == nil {
|
||||
ctx.router = DefaultRouter(ctx.spec, ctx.api)
|
||||
ctx.router = DefaultRouter(ctx.spec, ctx.api, WithDefaultRouterLoggerFunc(ctx.debugLogf))
|
||||
}
|
||||
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
|
|
@ -103,41 +105,75 @@ type RoutableAPI interface {
|
|||
DefaultConsumes() string
|
||||
}
|
||||
|
||||
// Router represents a swagger aware router
|
||||
// Router represents a swagger-aware router
|
||||
type Router interface {
|
||||
Lookup(method, path string) (*MatchedRoute, bool)
|
||||
OtherMethods(method, path string) []string
|
||||
}
|
||||
|
||||
type defaultRouteBuilder struct {
|
||||
spec *loads.Document
|
||||
analyzer *analysis.Spec
|
||||
api RoutableAPI
|
||||
records map[string][]denco.Record
|
||||
spec *loads.Document
|
||||
analyzer *analysis.Spec
|
||||
api RoutableAPI
|
||||
records map[string][]denco.Record
|
||||
debugLogf func(string, ...any) // a logging function to debug context and all components using it
|
||||
}
|
||||
|
||||
type defaultRouter struct {
|
||||
spec *loads.Document
|
||||
routers map[string]*denco.Router
|
||||
spec *loads.Document
|
||||
routers map[string]*denco.Router
|
||||
debugLogf func(string, ...any) // a logging function to debug context and all components using it
|
||||
}
|
||||
|
||||
func newDefaultRouteBuilder(spec *loads.Document, api RoutableAPI) *defaultRouteBuilder {
|
||||
func newDefaultRouteBuilder(spec *loads.Document, api RoutableAPI, opts ...DefaultRouterOpt) *defaultRouteBuilder {
|
||||
var o defaultRouterOpts
|
||||
for _, apply := range opts {
|
||||
apply(&o)
|
||||
}
|
||||
if o.debugLogf == nil {
|
||||
o.debugLogf = debugLogfFunc(nil) // defaults to standard logger
|
||||
}
|
||||
|
||||
return &defaultRouteBuilder{
|
||||
spec: spec,
|
||||
analyzer: analysis.New(spec.Spec()),
|
||||
api: api,
|
||||
records: make(map[string][]denco.Record),
|
||||
spec: spec,
|
||||
analyzer: analysis.New(spec.Spec()),
|
||||
api: api,
|
||||
records: make(map[string][]denco.Record),
|
||||
debugLogf: o.debugLogf,
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultRouter creates a default implemenation of the router
|
||||
func DefaultRouter(spec *loads.Document, api RoutableAPI) Router {
|
||||
builder := newDefaultRouteBuilder(spec, api)
|
||||
// DefaultRouterOpt allows to inject optional behavior to the default router.
|
||||
type DefaultRouterOpt func(*defaultRouterOpts)
|
||||
|
||||
type defaultRouterOpts struct {
|
||||
debugLogf func(string, ...any)
|
||||
}
|
||||
|
||||
// WithDefaultRouterLogger sets the debug logger for the default router.
|
||||
//
|
||||
// This is enabled only in DEBUG mode.
|
||||
func WithDefaultRouterLogger(lg logger.Logger) DefaultRouterOpt {
|
||||
return func(o *defaultRouterOpts) {
|
||||
o.debugLogf = debugLogfFunc(lg)
|
||||
}
|
||||
}
|
||||
|
||||
// WithDefaultRouterLoggerFunc sets a logging debug method for the default router.
|
||||
func WithDefaultRouterLoggerFunc(fn func(string, ...any)) DefaultRouterOpt {
|
||||
return func(o *defaultRouterOpts) {
|
||||
o.debugLogf = fn
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultRouter creates a default implementation of the router
|
||||
func DefaultRouter(spec *loads.Document, api RoutableAPI, opts ...DefaultRouterOpt) Router {
|
||||
builder := newDefaultRouteBuilder(spec, api, opts...)
|
||||
if spec != nil {
|
||||
for method, paths := range builder.analyzer.Operations() {
|
||||
for path, operation := range paths {
|
||||
fp := fpath.Join(spec.BasePath(), path)
|
||||
debugLog("adding route %s %s %q", method, fp, operation.ID)
|
||||
builder.debugLogf("adding route %s %s %q", method, fp, operation.ID)
|
||||
builder.AddRoute(method, fp, operation)
|
||||
}
|
||||
}
|
||||
|
|
@ -319,24 +355,24 @@ func (m *MatchedRoute) NeedsAuth() bool {
|
|||
|
||||
func (d *defaultRouter) Lookup(method, path string) (*MatchedRoute, bool) {
|
||||
mth := strings.ToUpper(method)
|
||||
debugLog("looking up route for %s %s", method, path)
|
||||
d.debugLogf("looking up route for %s %s", method, path)
|
||||
if Debug {
|
||||
if len(d.routers) == 0 {
|
||||
debugLog("there are no known routers")
|
||||
d.debugLogf("there are no known routers")
|
||||
}
|
||||
for meth := range d.routers {
|
||||
debugLog("got a router for %s", meth)
|
||||
d.debugLogf("got a router for %s", meth)
|
||||
}
|
||||
}
|
||||
if router, ok := d.routers[mth]; ok {
|
||||
if m, rp, ok := router.Lookup(fpath.Clean(path)); ok && m != nil {
|
||||
if entry, ok := m.(*routeEntry); ok {
|
||||
debugLog("found a route for %s %s with %d parameters", method, path, len(entry.Parameters))
|
||||
d.debugLogf("found a route for %s %s with %d parameters", method, path, len(entry.Parameters))
|
||||
var params RouteParams
|
||||
for _, p := range rp {
|
||||
v, err := pathUnescape(p.Value)
|
||||
v, err := url.PathUnescape(p.Value)
|
||||
if err != nil {
|
||||
debugLog("failed to escape %q: %v", p.Value, err)
|
||||
d.debugLogf("failed to escape %q: %v", p.Value, err)
|
||||
v = p.Value
|
||||
}
|
||||
// a workaround to handle fragment/composing parameters until they are supported in denco router
|
||||
|
|
@ -356,10 +392,10 @@ func (d *defaultRouter) Lookup(method, path string) (*MatchedRoute, bool) {
|
|||
return &MatchedRoute{routeEntry: *entry, Params: params}, true
|
||||
}
|
||||
} else {
|
||||
debugLog("couldn't find a route by path for %s %s", method, path)
|
||||
d.debugLogf("couldn't find a route by path for %s %s", method, path)
|
||||
}
|
||||
} else {
|
||||
debugLog("couldn't find a route by method for %s %s", method, path)
|
||||
d.debugLogf("couldn't find a route by method for %s %s", method, path)
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
|
@ -378,6 +414,10 @@ func (d *defaultRouter) OtherMethods(method, path string) []string {
|
|||
return methods
|
||||
}
|
||||
|
||||
func (d *defaultRouter) SetLogger(lg logger.Logger) {
|
||||
d.debugLogf = debugLogfFunc(lg)
|
||||
}
|
||||
|
||||
// convert swagger parameters per path segment into a denco parameter as multiple parameters per segment are not supported in denco
|
||||
var pathConverter = regexp.MustCompile(`{(.+?)}([^/]*)`)
|
||||
|
||||
|
|
@ -413,7 +453,7 @@ func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Oper
|
|||
bp = bp[:len(bp)-1]
|
||||
}
|
||||
|
||||
debugLog("operation: %#v", *operation)
|
||||
d.debugLogf("operation: %#v", *operation)
|
||||
if handler, ok := d.api.HandlerFor(method, strings.TrimPrefix(path, bp)); ok {
|
||||
consumes := d.analyzer.ConsumesFor(operation)
|
||||
produces := d.analyzer.ProducesFor(operation)
|
||||
|
|
@ -428,6 +468,8 @@ func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Oper
|
|||
produces = append(produces, defProduces)
|
||||
}
|
||||
|
||||
requestBinder := NewUntypedRequestBinder(parameters, d.spec.Spec(), d.api.Formats())
|
||||
requestBinder.setDebugLogf(d.debugLogf)
|
||||
record := denco.NewRecord(pathConverter.ReplaceAllString(path, ":$1"), &routeEntry{
|
||||
BasePath: bp,
|
||||
PathPattern: path,
|
||||
|
|
@ -439,7 +481,7 @@ func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Oper
|
|||
Producers: d.api.ProducersFor(normalizeOffers(produces)),
|
||||
Parameters: parameters,
|
||||
Formats: d.api.Formats(),
|
||||
Binder: NewUntypedRequestBinder(parameters, d.spec.Spec(), d.api.Formats()),
|
||||
Binder: requestBinder,
|
||||
Authenticators: d.buildAuthenticators(operation),
|
||||
Authorizer: d.api.Authorizer(),
|
||||
})
|
||||
|
|
@ -482,7 +524,8 @@ func (d *defaultRouteBuilder) Build() *defaultRouter {
|
|||
routers[method] = router
|
||||
}
|
||||
return &defaultRouter{
|
||||
spec: d.spec,
|
||||
routers: routers,
|
||||
spec: d.spec,
|
||||
routers: routers,
|
||||
debugLogf: d.debugLogf,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
77
vendor/github.com/go-openapi/runtime/middleware/spec.go
generated
vendored
77
vendor/github.com/go-openapi/runtime/middleware/spec.go
generated
vendored
|
|
@ -19,29 +19,84 @@ import (
|
|||
"path"
|
||||
)
|
||||
|
||||
// Spec creates a middleware to serve a swagger spec.
|
||||
const (
|
||||
contentTypeHeader = "Content-Type"
|
||||
applicationJSON = "application/json"
|
||||
)
|
||||
|
||||
// SpecOption can be applied to the Spec serving middleware
|
||||
type SpecOption func(*specOptions)
|
||||
|
||||
var defaultSpecOptions = specOptions{
|
||||
Path: "",
|
||||
Document: "swagger.json",
|
||||
}
|
||||
|
||||
type specOptions struct {
|
||||
Path string
|
||||
Document string
|
||||
}
|
||||
|
||||
func specOptionsWithDefaults(opts []SpecOption) specOptions {
|
||||
o := defaultSpecOptions
|
||||
for _, apply := range opts {
|
||||
apply(&o)
|
||||
}
|
||||
|
||||
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.
|
||||
// This can be useful if you want to serve the swagger spec from another path than /swagger.json
|
||||
func Spec(basePath string, b []byte, next http.Handler) http.Handler {
|
||||
//
|
||||
// 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").
|
||||
func Spec(basePath string, b []byte, next http.Handler, opts ...SpecOption) http.Handler {
|
||||
if basePath == "" {
|
||||
basePath = "/"
|
||||
}
|
||||
pth := path.Join(basePath, "swagger.json")
|
||||
o := specOptionsWithDefaults(opts)
|
||||
pth := path.Join(basePath, o.Path, o.Document)
|
||||
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == pth {
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
if path.Clean(r.URL.Path) == pth {
|
||||
rw.Header().Set(contentTypeHeader, applicationJSON)
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
//#nosec
|
||||
_, _ = rw.Write(b)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if next == nil {
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
if next != nil {
|
||||
next.ServeHTTP(rw, r)
|
||||
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(rw, r)
|
||||
|
||||
rw.Header().Set(contentTypeHeader, applicationJSON)
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
})
|
||||
}
|
||||
|
||||
// WithSpecPath sets the path to be joined to the base path of the Spec middleware.
|
||||
//
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
87
vendor/github.com/go-openapi/runtime/middleware/swaggerui.go
generated
vendored
87
vendor/github.com/go-openapi/runtime/middleware/swaggerui.go
generated
vendored
|
|
@ -8,40 +8,65 @@ import (
|
|||
"path"
|
||||
)
|
||||
|
||||
// SwaggerUIOpts configures the Swaggerui middlewares
|
||||
// SwaggerUIOpts configures the SwaggerUI middleware
|
||||
type SwaggerUIOpts struct {
|
||||
// BasePath for the UI path, defaults to: /
|
||||
// BasePath for the API, defaults to: /
|
||||
BasePath string
|
||||
// Path combines with BasePath for the full UI path, defaults to: docs
|
||||
|
||||
// Path combines with BasePath to construct the path to the UI, defaults to: "docs".
|
||||
Path string
|
||||
// SpecURL the url to find the spec for
|
||||
|
||||
// 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
|
||||
OAuthCallbackURL string
|
||||
|
||||
// The three components needed to embed swagger-ui
|
||||
SwaggerURL string
|
||||
|
||||
// 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
|
||||
|
||||
// Title for the documentation site, default to: API documentation
|
||||
Title string
|
||||
}
|
||||
|
||||
// EnsureDefaults in case some options are missing
|
||||
func (r *SwaggerUIOpts) EnsureDefaults() {
|
||||
if r.BasePath == "" {
|
||||
r.BasePath = "/"
|
||||
r.ensureDefaults()
|
||||
|
||||
if r.Template == "" {
|
||||
r.Template = swaggeruiTemplate
|
||||
}
|
||||
if r.Path == "" {
|
||||
r.Path = defaultDocsPath
|
||||
}
|
||||
if r.SpecURL == "" {
|
||||
r.SpecURL = defaultDocsURL
|
||||
}
|
||||
|
||||
func (r *SwaggerUIOpts) EnsureDefaultsOauth2() {
|
||||
r.ensureDefaults()
|
||||
|
||||
if r.Template == "" {
|
||||
r.Template = swaggerOAuthTemplate
|
||||
}
|
||||
}
|
||||
|
||||
func (r *SwaggerUIOpts) ensureDefaults() {
|
||||
common := toCommonUIOptions(r)
|
||||
common.EnsureDefaults()
|
||||
fromCommonToAnyOptions(common, r)
|
||||
|
||||
// swaggerui-specifics
|
||||
if r.OAuthCallbackURL == "" {
|
||||
r.OAuthCallbackURL = path.Join(r.BasePath, r.Path, "oauth2-callback")
|
||||
}
|
||||
|
|
@ -60,40 +85,22 @@ func (r *SwaggerUIOpts) EnsureDefaults() {
|
|||
if r.Favicon32 == "" {
|
||||
r.Favicon32 = swaggerFavicon32Latest
|
||||
}
|
||||
if r.Title == "" {
|
||||
r.Title = defaultDocsTitle
|
||||
}
|
||||
}
|
||||
|
||||
// SwaggerUI creates a middleware to serve a documentation site for a swagger spec.
|
||||
//
|
||||
// This allows for altering the spec before starting the http listener.
|
||||
func SwaggerUI(opts SwaggerUIOpts, next http.Handler) http.Handler {
|
||||
opts.EnsureDefaults()
|
||||
|
||||
pth := path.Join(opts.BasePath, opts.Path)
|
||||
tmpl := template.Must(template.New("swaggerui").Parse(swaggeruiTemplate))
|
||||
tmpl := template.Must(template.New("swaggerui").Parse(opts.Template))
|
||||
assets := bytes.NewBuffer(nil)
|
||||
if err := tmpl.Execute(assets, opts); err != nil {
|
||||
panic(fmt.Errorf("cannot execute template: %w", err))
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
_ = tmpl.Execute(buf, &opts)
|
||||
b := buf.Bytes()
|
||||
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
if path.Join(r.URL.Path) == pth {
|
||||
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
|
||||
_, _ = rw.Write(b)
|
||||
return
|
||||
}
|
||||
|
||||
if next == nil {
|
||||
rw.Header().Set("Content-Type", "text/plain")
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
_, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(rw, r)
|
||||
})
|
||||
return serveUI(pth, assets.Bytes(), next)
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
|
|||
31
vendor/github.com/go-openapi/runtime/middleware/swaggerui_oauth2.go
generated
vendored
31
vendor/github.com/go-openapi/runtime/middleware/swaggerui_oauth2.go
generated
vendored
|
|
@ -4,37 +4,20 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func SwaggerUIOAuth2Callback(opts SwaggerUIOpts, next http.Handler) http.Handler {
|
||||
opts.EnsureDefaults()
|
||||
opts.EnsureDefaultsOauth2()
|
||||
|
||||
pth := opts.OAuthCallbackURL
|
||||
tmpl := template.Must(template.New("swaggeroauth").Parse(swaggerOAuthTemplate))
|
||||
tmpl := template.Must(template.New("swaggeroauth").Parse(opts.Template))
|
||||
assets := bytes.NewBuffer(nil)
|
||||
if err := tmpl.Execute(assets, opts); err != nil {
|
||||
panic(fmt.Errorf("cannot execute template: %w", err))
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
_ = tmpl.Execute(buf, &opts)
|
||||
b := buf.Bytes()
|
||||
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
if path.Join(r.URL.Path) == pth {
|
||||
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
|
||||
_, _ = rw.Write(b)
|
||||
return
|
||||
}
|
||||
|
||||
if next == nil {
|
||||
rw.Header().Set("Content-Type", "text/plain")
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
_, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(rw, r)
|
||||
})
|
||||
return serveUI(pth, assets.Bytes(), next)
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
|
|||
8
vendor/github.com/go-openapi/runtime/middleware/ui_defaults.go
generated
vendored
8
vendor/github.com/go-openapi/runtime/middleware/ui_defaults.go
generated
vendored
|
|
@ -1,8 +0,0 @@
|
|||
package middleware
|
||||
|
||||
const (
|
||||
// constants that are common to all UI-serving middlewares
|
||||
defaultDocsPath = "docs"
|
||||
defaultDocsURL = "/swagger.json"
|
||||
defaultDocsTitle = "API Documentation"
|
||||
)
|
||||
173
vendor/github.com/go-openapi/runtime/middleware/ui_options.go
generated
vendored
Normal file
173
vendor/github.com/go-openapi/runtime/middleware/ui_options.go
generated
vendored
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// constants that are common to all UI-serving middlewares
|
||||
defaultDocsPath = "docs"
|
||||
defaultDocsURL = "/swagger.json"
|
||||
defaultDocsTitle = "API Documentation"
|
||||
)
|
||||
|
||||
// uiOptions defines common options for UI serving middlewares.
|
||||
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
|
||||
}
|
||||
|
||||
// toCommonUIOptions converts any UI option type to retain the common options.
|
||||
//
|
||||
// This uses gob encoding/decoding to convert common fields from one struct to another.
|
||||
func toCommonUIOptions(opts interface{}) uiOptions {
|
||||
var buf bytes.Buffer
|
||||
enc := gob.NewEncoder(&buf)
|
||||
dec := gob.NewDecoder(&buf)
|
||||
var o uiOptions
|
||||
err := enc.Encode(opts)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = dec.Decode(&o)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func fromCommonToAnyOptions[T any](source uiOptions, target *T) {
|
||||
var buf bytes.Buffer
|
||||
enc := gob.NewEncoder(&buf)
|
||||
dec := gob.NewDecoder(&buf)
|
||||
err := enc.Encode(source)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = dec.Decode(target)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// UIOption can be applied to UI serving middleware, such as Context.APIHandler or
|
||||
// Context.APIHandlerSwaggerUI to alter the defaut behavior.
|
||||
type UIOption func(*uiOptions)
|
||||
|
||||
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.
|
||||
//
|
||||
// By default, Context middleware sets this value to the API base path.
|
||||
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}.
|
||||
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"
|
||||
func WithUISpecURL(specURL string) UIOption {
|
||||
return func(o *uiOptions) {
|
||||
o.SpecURL = specURL
|
||||
}
|
||||
}
|
||||
|
||||
// WithUITitle sets the title of the UI.
|
||||
//
|
||||
// By default, Context middleware sets this value to the title found in the API spec.
|
||||
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.
|
||||
func WithTemplate(tpl string) UIOption {
|
||||
return func(o *uiOptions) {
|
||||
o.Template = tpl
|
||||
}
|
||||
}
|
||||
|
||||
// EnsureDefaults in case some options are missing
|
||||
func (r *uiOptions) EnsureDefaults() {
|
||||
if r.BasePath == "" {
|
||||
r.BasePath = "/"
|
||||
}
|
||||
if r.Path == "" {
|
||||
r.Path = defaultDocsPath
|
||||
}
|
||||
if r.SpecURL == "" {
|
||||
r.SpecURL = defaultDocsURL
|
||||
}
|
||||
if r.Title == "" {
|
||||
r.Title = defaultDocsTitle
|
||||
}
|
||||
}
|
||||
|
||||
// serveUI creates a middleware that serves a templated asset as text/html.
|
||||
func serveUI(pth string, assets []byte, next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
if path.Clean(r.URL.Path) == pth {
|
||||
rw.Header().Set(contentTypeHeader, "text/html; charset=utf-8")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
_, _ = rw.Write(assets)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if next != nil {
|
||||
next.ServeHTTP(rw, r)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
rw.Header().Set(contentTypeHeader, "text/plain")
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
_, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
|
||||
})
|
||||
}
|
||||
12
vendor/github.com/go-openapi/runtime/middleware/validation.go
generated
vendored
12
vendor/github.com/go-openapi/runtime/middleware/validation.go
generated
vendored
|
|
@ -35,7 +35,6 @@ type validation struct {
|
|||
|
||||
// ContentType validates the content type of a request
|
||||
func validateContentType(allowed []string, actual string) error {
|
||||
debugLog("validating content type for %q against [%s]", actual, strings.Join(allowed, ", "))
|
||||
if len(allowed) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -57,13 +56,13 @@ func validateContentType(allowed []string, actual string) error {
|
|||
}
|
||||
|
||||
func validateRequest(ctx *Context, request *http.Request, route *MatchedRoute) *validation {
|
||||
debugLog("validating request %s %s", request.Method, request.URL.EscapedPath())
|
||||
validate := &validation{
|
||||
context: ctx,
|
||||
request: request,
|
||||
route: route,
|
||||
bound: make(map[string]interface{}),
|
||||
}
|
||||
validate.debugLogf("validating request %s %s", request.Method, request.URL.EscapedPath())
|
||||
|
||||
validate.contentType()
|
||||
if len(validate.result) == 0 {
|
||||
|
|
@ -76,8 +75,12 @@ func validateRequest(ctx *Context, request *http.Request, route *MatchedRoute) *
|
|||
return validate
|
||||
}
|
||||
|
||||
func (v *validation) debugLogf(format string, args ...any) {
|
||||
v.context.debugLogf(format, args...)
|
||||
}
|
||||
|
||||
func (v *validation) parameters() {
|
||||
debugLog("validating request parameters for %s %s", v.request.Method, v.request.URL.EscapedPath())
|
||||
v.debugLogf("validating request parameters for %s %s", v.request.Method, v.request.URL.EscapedPath())
|
||||
if result := v.route.Binder.Bind(v.request, v.route.Params, v.route.Consumer, v.bound); result != nil {
|
||||
if result.Error() == "validation failure list" {
|
||||
for _, e := range result.(*errors.Validation).Value.([]interface{}) {
|
||||
|
|
@ -91,7 +94,7 @@ func (v *validation) parameters() {
|
|||
|
||||
func (v *validation) contentType() {
|
||||
if len(v.result) == 0 && runtime.HasBody(v.request) {
|
||||
debugLog("validating body content type for %s %s", v.request.Method, v.request.URL.EscapedPath())
|
||||
v.debugLogf("validating body content type for %s %s", v.request.Method, v.request.URL.EscapedPath())
|
||||
ct, _, req, err := v.context.ContentType(v.request)
|
||||
if err != nil {
|
||||
v.result = append(v.result, err)
|
||||
|
|
@ -100,6 +103,7 @@ func (v *validation) contentType() {
|
|||
}
|
||||
|
||||
if len(v.result) == 0 {
|
||||
v.debugLogf("validating content type for %q against [%s]", ct, strings.Join(v.route.Consumes, ", "))
|
||||
if err := validateContentType(v.route.Consumes, ct); err != nil {
|
||||
v.result = append(v.result, err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue