summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/go-openapi/runtime/middleware
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/go-openapi/runtime/middleware')
-rw-r--r--vendor/github.com/go-openapi/runtime/middleware/context.go40
-rw-r--r--vendor/github.com/go-openapi/runtime/middleware/denco/router.go8
-rw-r--r--vendor/github.com/go-openapi/runtime/middleware/not_implemented.go23
-rw-r--r--vendor/github.com/go-openapi/runtime/middleware/parameter.go7
-rw-r--r--vendor/github.com/go-openapi/runtime/middleware/redoc.go10
-rw-r--r--vendor/github.com/go-openapi/runtime/middleware/request.go16
-rw-r--r--vendor/github.com/go-openapi/runtime/middleware/router.go9
-rw-r--r--vendor/github.com/go-openapi/runtime/middleware/swaggerui.go162
-rw-r--r--vendor/github.com/go-openapi/runtime/middleware/untyped/api.go4
-rw-r--r--vendor/github.com/go-openapi/runtime/middleware/validation.go8
10 files changed, 254 insertions, 33 deletions
diff --git a/vendor/github.com/go-openapi/runtime/middleware/context.go b/vendor/github.com/go-openapi/runtime/middleware/context.go
index 54a8c21f15..fba5748db5 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/context.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/context.go
@@ -21,16 +21,16 @@ import (
"strings"
"sync"
- "github.com/go-openapi/runtime/security"
-
"github.com/go-openapi/analysis"
"github.com/go-openapi/errors"
"github.com/go-openapi/loads"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/logger"
"github.com/go-openapi/runtime/middleware/untyped"
- "github.com/go-openapi/spec"
- "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/runtime/security"
)
// Debug when true turns on verbose logging
@@ -280,8 +280,8 @@ func (c *Context) RequiredProduces() []string {
// if the request is not valid an error will be returned
func (c *Context) BindValidRequest(request *http.Request, route *MatchedRoute, binder RequestBinder) error {
var res []error
+ var requestContentType string
- requestContentType := "*/*"
// check and validate content type, select consumer
if runtime.HasBody(request) {
ct, _, err := runtime.ContentType(request.Header)
@@ -304,7 +304,13 @@ func (c *Context) BindValidRequest(request *http.Request, route *MatchedRoute, b
}
// check and validate the response format
- if len(res) == 0 && runtime.HasBody(request) {
+ if len(res) == 0 {
+ // if the route does not provide Produces and a default contentType could not be identified
+ // based on a body, typical for GET and DELETE requests, then default contentType to.
+ if len(route.Produces) == 0 && requestContentType == "" {
+ requestContentType = "*/*"
+ }
+
if str := NegotiateContentType(request, route.Produces, requestContentType); str == "" {
res = append(res, errors.InvalidResponseFormat(request.Header.Get(runtime.HeaderAccept), route.Produces))
}
@@ -433,6 +439,8 @@ func (c *Context) Authorize(request *http.Request, route *MatchedRoute) (interfa
}
}
+ rCtx = request.Context()
+
rCtx = stdContext.WithValue(rCtx, ctxSecurityPrincipal, usr)
rCtx = stdContext.WithValue(rCtx, ctxSecurityScopes, route.Authenticator.AllScopes())
return usr, request.WithContext(rCtx), nil
@@ -559,6 +567,26 @@ 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 {
+ 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
+ }
+
+ swaggerUIOpts := SwaggerUIOpts{
+ BasePath: c.BasePath(),
+ Title: title,
+ }
+
+ return Spec("", c.spec.Raw(), SwaggerUI(swaggerUIOpts, c.RoutesHandler(b)))
+}
+
// 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 {
b := builder
diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/router.go b/vendor/github.com/go-openapi/runtime/middleware/denco/router.go
index 73703fddec..ecacc31ff6 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/denco/router.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/denco/router.go
@@ -17,6 +17,9 @@ const (
// TerminationCharacter is a special character for end of path.
TerminationCharacter = '#'
+ // SeparatorCharacter separates path segments.
+ SeparatorCharacter = '/'
+
// MaxSize is max size of records and internal slice.
MaxSize = (1 << 22) - 1
)
@@ -420,10 +423,11 @@ type record struct {
// makeRecords returns the records that use to build Double-Arrays.
func makeRecords(srcs []Record) (statics, params []*record) {
- spChars := string([]byte{ParamCharacter, WildcardCharacter})
termChar := string(TerminationCharacter)
+ paramPrefix := string(SeparatorCharacter) + string(ParamCharacter)
+ wildcardPrefix := string(SeparatorCharacter) + string(WildcardCharacter)
for _, r := range srcs {
- if strings.ContainsAny(r.Key, spChars) {
+ if strings.Contains(r.Key, paramPrefix) || strings.Contains(r.Key, wildcardPrefix) {
r.Key += termChar
params = append(params, &record{Record: r})
} else {
diff --git a/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go b/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go
index 466f553db4..bc6942a0f1 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go
@@ -38,11 +38,30 @@ func (e *errorResp) WriteResponse(rw http.ResponseWriter, producer runtime.Produ
rw.WriteHeader(http.StatusInternalServerError)
}
if err := producer.Produce(rw, e.response); err != nil {
- panic(err)
+ Logger.Printf("failed to write error response: %v", err)
}
}
// NotImplemented the error response when the response is not implemented
func NotImplemented(message string) Responder {
- return &errorResp{http.StatusNotImplemented, message, make(http.Header)}
+ return Error(http.StatusNotImplemented, message)
+}
+
+// Error creates a generic responder for returning errors, the data will be serialized
+// with the matching producer for the request
+func Error(code int, data interface{}, headers ...http.Header) Responder {
+ var hdr http.Header
+ for _, h := range headers {
+ for k, v := range h {
+ if hdr == nil {
+ hdr = make(http.Header)
+ }
+ hdr[k] = v
+ }
+ }
+ return &errorResp{
+ code: code,
+ response: data,
+ headers: hdr,
+ }
}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/parameter.go b/vendor/github.com/go-openapi/runtime/middleware/parameter.go
index 8975b6e1c8..8fa0cf4e46 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/parameter.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/parameter.go
@@ -24,11 +24,12 @@ import (
"strconv"
"github.com/go-openapi/errors"
- "github.com/go-openapi/runtime"
"github.com/go-openapi/spec"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
+
+ "github.com/go-openapi/runtime"
)
const defaultMaxMemory = 32 << 20
@@ -275,7 +276,7 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue in
}
if (!hasKey || (!p.parameter.AllowEmptyValue && data == "")) && p.parameter.Required && p.parameter.Default == nil {
- return errors.Required(p.Name, p.parameter.In)
+ return errors.Required(p.Name, p.parameter.In, data)
}
ok, err := p.tryUnmarshaler(target, defaultValue, data)
@@ -450,7 +451,7 @@ func (p *untypedParamBinder) readFormattedSliceFieldValue(data string, target re
func (p *untypedParamBinder) setSliceFieldValue(target reflect.Value, defaultValue interface{}, data []string, hasKey bool) error {
sz := len(data)
if (!hasKey || (!p.parameter.AllowEmptyValue && (sz == 0 || (sz == 1 && data[0] == "")))) && p.parameter.Required && defaultValue == nil {
- return errors.Required(p.Name, p.parameter.In)
+ return errors.Required(p.Name, p.parameter.In, data)
}
defVal := reflect.Zero(target.Type())
diff --git a/vendor/github.com/go-openapi/runtime/middleware/redoc.go b/vendor/github.com/go-openapi/runtime/middleware/redoc.go
index 21277948c0..019c854295 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/redoc.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/redoc.go
@@ -16,7 +16,7 @@ type RedocOpts struct {
Path string
// SpecURL the url to find the spec for
SpecURL string
- // RedocURL for the js that generates the redoc site, defaults to: https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js
+ // 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
@@ -74,13 +74,15 @@ func Redoc(opts RedocOpts, next http.Handler) http.Handler {
}
const (
- redocLatest = "https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js"
+ redocLatest = "https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js"
redocTemplate = `<!DOCTYPE html>
<html>
<head>
<title>{{ .Title }}</title>
- <!-- needed for adaptive design -->
- <meta name="viewport" content="width=device-width, initial-scale=1">
+ <!-- needed for adaptive design -->
+ <meta charset="utf-8"/>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
<!--
ReDoc doesn't change outer page styles
diff --git a/vendor/github.com/go-openapi/runtime/middleware/request.go b/vendor/github.com/go-openapi/runtime/middleware/request.go
index ee725f587a..760c37861d 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/request.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/request.go
@@ -19,26 +19,27 @@ import (
"reflect"
"github.com/go-openapi/errors"
- "github.com/go-openapi/runtime"
"github.com/go-openapi/spec"
"github.com/go-openapi/strfmt"
+
+ "github.com/go-openapi/runtime"
)
-// RequestBinder binds and validates the data from a http request
-type untypedRequestBinder struct {
+// UntypedRequestBinder binds and validates the data from a http request
+type UntypedRequestBinder struct {
Spec *spec.Swagger
Parameters map[string]spec.Parameter
Formats strfmt.Registry
paramBinders map[string]*untypedParamBinder
}
-// NewRequestBinder creates a new binder for reading a request.
-func newUntypedRequestBinder(parameters map[string]spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *untypedRequestBinder {
+// NewUntypedRequestBinder creates a new binder for reading a request.
+func NewUntypedRequestBinder(parameters map[string]spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *UntypedRequestBinder {
binders := make(map[string]*untypedParamBinder)
for fieldName, param := range parameters {
binders[fieldName] = newUntypedParamBinder(param, spec, formats)
}
- return &untypedRequestBinder{
+ return &UntypedRequestBinder{
Parameters: parameters,
paramBinders: binders,
Spec: spec,
@@ -47,7 +48,7 @@ func newUntypedRequestBinder(parameters map[string]spec.Parameter, spec *spec.Sw
}
// Bind perform the databinding and validation
-func (o *untypedRequestBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, data interface{}) error {
+func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, data interface{}) error {
val := reflect.Indirect(reflect.ValueOf(data))
isMap := val.Kind() == reflect.Map
var result []error
@@ -71,7 +72,6 @@ func (o *untypedRequestBinder) Bind(request *http.Request, routeParams RoutePara
}
}
target = reflect.Indirect(reflect.New(tpe))
-
}
if !target.IsValid() {
diff --git a/vendor/github.com/go-openapi/runtime/middleware/router.go b/vendor/github.com/go-openapi/runtime/middleware/router.go
index 539d8471a8..02768bade2 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/router.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/router.go
@@ -26,10 +26,11 @@ import (
"github.com/go-openapi/analysis"
"github.com/go-openapi/errors"
"github.com/go-openapi/loads"
- "github.com/go-openapi/runtime"
- "github.com/go-openapi/runtime/middleware/denco"
"github.com/go-openapi/spec"
"github.com/go-openapi/strfmt"
+
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/runtime/middleware/denco"
)
// RouteParam is a object to capture route params in a framework agnostic way.
@@ -290,7 +291,7 @@ type routeEntry struct {
Parameters map[string]spec.Parameter
Handler http.Handler
Formats strfmt.Registry
- Binder *untypedRequestBinder
+ Binder *UntypedRequestBinder
Authenticators RouteAuthenticators
Authorizer runtime.Authorizer
}
@@ -428,7 +429,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: NewUntypedRequestBinder(parameters, d.spec.Spec(), d.api.Formats()),
Authenticators: d.buildAuthenticators(operation),
Authorizer: d.api.Authorizer(),
})
diff --git a/vendor/github.com/go-openapi/runtime/middleware/swaggerui.go b/vendor/github.com/go-openapi/runtime/middleware/swaggerui.go
new file mode 100644
index 0000000000..2c92f5c91f
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/swaggerui.go
@@ -0,0 +1,162 @@
+package middleware
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "net/http"
+ "path"
+)
+
+// SwaggerUIOpts configures the Swaggerui middlewares
+type SwaggerUIOpts struct {
+ // BasePath for the UI path, defaults to: /
+ BasePath string
+ // Path combines with BasePath for the full UI path, defaults to: docs
+ Path string
+ // SpecURL the url to find the spec for
+ SpecURL string
+
+ // The three components needed to embed swagger-ui
+ 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 = "/"
+ }
+ if r.Path == "" {
+ r.Path = "docs"
+ }
+ if r.SpecURL == "" {
+ r.SpecURL = "/swagger.json"
+ }
+ if r.SwaggerURL == "" {
+ r.SwaggerURL = swaggerLatest
+ }
+ if r.SwaggerPresetURL == "" {
+ r.SwaggerPresetURL = swaggerPresetLatest
+ }
+ if r.SwaggerStylesURL == "" {
+ r.SwaggerStylesURL = swaggerStylesLatest
+ }
+ if r.Favicon16 == "" {
+ r.Favicon16 = swaggerFavicon16Latest
+ }
+ if r.Favicon32 == "" {
+ r.Favicon32 = swaggerFavicon32Latest
+ }
+ if r.Title == "" {
+ r.Title = "API documentation"
+ }
+}
+
+// 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))
+
+ 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)
+ })
+}
+
+const (
+ swaggerLatest = "https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js"
+ swaggerPresetLatest = "https://unpkg.com/swagger-ui-dist/swagger-ui-standalone-preset.js"
+ swaggerStylesLatest = "https://unpkg.com/swagger-ui-dist/swagger-ui.css"
+ swaggerFavicon32Latest = "https://unpkg.com/swagger-ui-dist/favicon-32x32.png"
+ swaggerFavicon16Latest = "https://unpkg.com/swagger-ui-dist/favicon-16x16.png"
+ swaggeruiTemplate = `
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <title>{{ .Title }}</title>
+
+ <link rel="stylesheet" type="text/css" href="{{ .SwaggerStylesURL }}" >
+ <link rel="icon" type="image/png" href="{{ .Favicon32 }}" sizes="32x32" />
+ <link rel="icon" type="image/png" href="{{ .Favicon16 }}" sizes="16x16" />
+ <style>
+ html
+ {
+ box-sizing: border-box;
+ overflow: -moz-scrollbars-vertical;
+ overflow-y: scroll;
+ }
+
+ *,
+ *:before,
+ *:after
+ {
+ box-sizing: inherit;
+ }
+
+ body
+ {
+ margin:0;
+ background: #fafafa;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div id="swagger-ui"></div>
+
+ <script src="{{ .SwaggerURL }}"> </script>
+ <script src="{{ .SwaggerPresetURL }}"> </script>
+ <script>
+ window.onload = function() {
+ // Begin Swagger UI call region
+ const ui = SwaggerUIBundle({
+ url: '{{ .SpecURL }}',
+ dom_id: '#swagger-ui',
+ deepLinking: true,
+ presets: [
+ SwaggerUIBundle.presets.apis,
+ SwaggerUIStandalonePreset
+ ],
+ plugins: [
+ SwaggerUIBundle.plugins.DownloadUrl
+ ],
+ layout: "StandaloneLayout"
+ })
+ // End Swagger UI call region
+
+ window.ui = ui
+ }
+ </script>
+ </body>
+</html>
+`
+)
diff --git a/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go b/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go
index 8226b1ed1c..39a85f7d9e 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go
@@ -23,9 +23,10 @@ import (
"github.com/go-openapi/analysis"
"github.com/go-openapi/errors"
"github.com/go-openapi/loads"
- "github.com/go-openapi/runtime"
"github.com/go-openapi/spec"
"github.com/go-openapi/strfmt"
+
+ "github.com/go-openapi/runtime"
)
// NewAPI creates the default untyped API
@@ -244,7 +245,6 @@ func (d *API) validate() error {
}
func (d *API) verify(name string, registrations []string, expectations []string) error {
-
sort.Strings(registrations)
sort.Strings(expectations)
diff --git a/vendor/github.com/go-openapi/runtime/middleware/validation.go b/vendor/github.com/go-openapi/runtime/middleware/validation.go
index bb8df3cb3d..1f0135b578 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/validation.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/validation.go
@@ -20,8 +20,9 @@ import (
"strings"
"github.com/go-openapi/errors"
- "github.com/go-openapi/runtime"
"github.com/go-openapi/swag"
+
+ "github.com/go-openapi/runtime"
)
type validation struct {
@@ -115,7 +116,10 @@ func (v *validation) contentType() {
}
func (v *validation) responseFormat() {
- if str, rCtx := v.context.ResponseFormat(v.request, v.route.Produces); str == "" && runtime.HasBody(v.request) {
+ // if the route provides values for Produces and no format could be identify then return an error.
+ // if the route does not specify values for Produces then treat request as valid since the API designer
+ // choose not to specify the format for responses.
+ if str, rCtx := v.context.ResponseFormat(v.request, v.route.Produces); str == "" && len(v.route.Produces) > 0 {
v.request = rCtx
v.result = append(v.result, errors.InvalidResponseFormat(v.request.Header.Get(runtime.HeaderAccept), v.route.Produces))
}