func (c *Context) AllowedMethods(request *http.Request) []string {
	return c.router.OtherMethods(request.Method, request.URL.EscapedPath())
}
AllowedMethods gets the allowed methods for the path of this request
package middleware
import (
	stdContext "context"
	"fmt"
	"net/http"
	"strings"
	"sync"
	"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/runtime/security"
)
var Debug = logger.DebugEnabled()
var Logger logger.Logger = logger.StandardLogger{}
func debugLog(format string, args ...interface{}) {
	if Debug {
		Logger.Printf(format, args...)
	}
}
type Builder func(http.Handler) http.Handler
func PassthroughBuilder(handler http.Handler) http.Handler { return handler }
type RequestBinder interface {
	BindRequest(*http.Request, *MatchedRoute) error
}
type Responder interface {
	WriteResponse(http.ResponseWriter, runtime.Producer)
}
type ResponderFunc func(http.ResponseWriter, runtime.Producer)
func (fn ResponderFunc) WriteResponse(rw http.ResponseWriter, pr runtime.Producer) {
	fn(rw, pr)
}
type Context struct {
	spec     *loads.Document
	analyzer *analysis.Spec
	api      RoutableAPI
	router   Router
}
type routableUntypedAPI struct {
	api             *untyped.API
	hlock           *sync.Mutex
	handlers        map[string]map[string]http.Handler
	defaultConsumes string
	defaultProduces string
}
func newRoutableUntypedAPI(spec *loads.Document, api *untyped.API, context *Context) *routableUntypedAPI {
	var handlers map[string]map[string]http.Handler
	if spec == nil || api == nil {
		return nil
	}
	analyzer := analysis.New(spec.Spec())
	for method, hls := range analyzer.Operations() {
		um := strings.ToUpper(method)
		for path, op := range hls {
			schemes := analyzer.SecurityRequirementsFor(op)
			if oh, ok := api.OperationHandlerFor(method, path); ok {
				if handlers == nil {
					handlers = make(map[string]map[string]http.Handler)
				}
				if b, ok := handlers[um]; !ok || b == nil {
					handlers[um] = make(map[string]http.Handler)
				}
				var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					route, rCtx, _ := context.RouteInfo(r)
					if rCtx != nil {
						r = rCtx
					}
					var bound interface{}
					var validation error
					bound, r, validation = context.BindAndValidate(r, route)
					if validation != nil {
						context.Respond(w, r, route.Produces, route, validation)
						return
					}
					result, err := oh.Handle(bound)
					if err != nil {
						context.Respond(w, r, route.Produces, route, err)
						return
					}
					context.Respond(w, r, route.Produces, route, result)
				})
				if len(schemes) > 0 {
					handler = newSecureAPI(context, handler)
				}
				handlers[um][path] = handler
			}
		}
	}
	return &routableUntypedAPI{
		api:             api,
		hlock:           new(sync.Mutex),
		handlers:        handlers,
		defaultProduces: api.DefaultProduces,
		defaultConsumes: api.DefaultConsumes,
	}
}
func (r *routableUntypedAPI) HandlerFor(method, path string) (http.Handler, bool) {
	r.hlock.Lock()
	paths, ok := r.handlers[strings.ToUpper(method)]
	if !ok {
		r.hlock.Unlock()
		return nil, false
	}
	handler, ok := paths[path]
	r.hlock.Unlock()
	return handler, ok
}
func (r *routableUntypedAPI) ServeErrorFor(operationID string) func(http.ResponseWriter, *http.Request, error) {
	return r.api.ServeError
}
func (r *routableUntypedAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
	return r.api.ConsumersFor(mediaTypes)
}
func (r *routableUntypedAPI) ProducersFor(mediaTypes []string) map[string]runtime.Producer {
	return r.api.ProducersFor(mediaTypes)
}
func (r *routableUntypedAPI) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator {
	return r.api.AuthenticatorsFor(schemes)
}
func (r *routableUntypedAPI) Authorizer() runtime.Authorizer {
	return r.api.Authorizer()
}
func (r *routableUntypedAPI) Formats() strfmt.Registry {
	return r.api.Formats()
}
func (r *routableUntypedAPI) DefaultProduces() string {
	return r.defaultProduces
}
func (r *routableUntypedAPI) DefaultConsumes() string {
	return r.defaultConsumes
}
func NewRoutableContext(spec *loads.Document, routableAPI RoutableAPI, routes Router) *Context {
	var an *analysis.Spec
	if spec != nil {
		an = analysis.New(spec.Spec())
	}
	ctx := &Context{spec: spec, api: routableAPI, analyzer: an, router: routes}
	return ctx
}
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.api = newRoutableUntypedAPI(spec, api, ctx)
	ctx.router = routes
	return ctx
}
func Serve(spec *loads.Document, api *untyped.API) http.Handler {
	return ServeWithBuilder(spec, api, PassthroughBuilder)
}
func ServeWithBuilder(spec *loads.Document, api *untyped.API, builder Builder) http.Handler {
	context := NewContext(spec, api, nil)
	return context.APIHandler(builder)
}
type contextKey int8
const (
	_ contextKey = iota
	ctxContentType
	ctxResponseFormat
	ctxMatchedRoute
	ctxBoundParams
	ctxSecurityPrincipal
	ctxSecurityScopes
)
func MatchedRouteFrom(req *http.Request) *MatchedRoute {
	mr := req.Context().Value(ctxMatchedRoute)
	if mr == nil {
		return nil
	}
	if res, ok := mr.(*MatchedRoute); ok {
		return res
	}
	return nil
}
func SecurityPrincipalFrom(req *http.Request) interface{} {
	return req.Context().Value(ctxSecurityPrincipal)
}
func SecurityScopesFrom(req *http.Request) []string {
	rs := req.Context().Value(ctxSecurityScopes)
	if res, ok := rs.([]string); ok {
		return res
	}
	return nil
}
type contentTypeValue struct {
	MediaType string
	Charset   string
}
func (c *Context) BasePath() string {
	return c.spec.BasePath()
}
func (c *Context) RequiredProduces() []string {
	return c.analyzer.RequiredProduces()
}
func (c *Context) BindValidRequest(request *http.Request, route *MatchedRoute, binder RequestBinder) error {
	var res []error
	var requestContentType string
	if runtime.HasBody(request) {
		ct, _, err := runtime.ContentType(request.Header)
		if err != nil {
			res = append(res, err)
		} else {
			if err := validateContentType(route.Consumes, ct); err != nil {
				res = append(res, err)
			}
			if len(res) == 0 {
				cons, ok := route.Consumers[ct]
				if !ok {
					res = append(res, errors.New(500, "no consumer registered for %s", ct))
				} else {
					route.Consumer = cons
					requestContentType = ct
				}
			}
		}
	}
	if len(res) == 0 {
		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))
		}
	}
	if binder != nil && len(res) == 0 {
		if err := binder.BindRequest(request, route); err != nil {
			return err
		}
	}
	if len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}
func (c *Context) ContentType(request *http.Request) (string, string, *http.Request, error) {
	var rCtx = request.Context()
	if v, ok := rCtx.Value(ctxContentType).(*contentTypeValue); ok {
		return v.MediaType, v.Charset, request, nil
	}
	mt, cs, err := runtime.ContentType(request.Header)
	if err != nil {
		return "", "", nil, err
	}
	rCtx = stdContext.WithValue(rCtx, ctxContentType, &contentTypeValue{mt, cs})
	return mt, cs, request.WithContext(rCtx), nil
}
func (c *Context) LookupRoute(request *http.Request) (*MatchedRoute, bool) {
	if route, ok := c.router.Lookup(request.Method, request.URL.EscapedPath()); ok {
		return route, ok
	}
	return nil, false
}
func (c *Context) RouteInfo(request *http.Request) (*MatchedRoute, *http.Request, bool) {
	var rCtx = request.Context()
	if v, ok := rCtx.Value(ctxMatchedRoute).(*MatchedRoute); ok {
		return v, request, ok
	}
	if route, ok := c.LookupRoute(request); ok {
		rCtx = stdContext.WithValue(rCtx, ctxMatchedRoute, route)
		return route, request.WithContext(rCtx), ok
	}
	return nil, nil, false
}
func (c *Context) ResponseFormat(r *http.Request, offers []string) (string, *http.Request) {
	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)
		return v, r
	}
	format := NegotiateContentType(r, offers, "")
	if format != "" {
		debugLog("[%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)
	return format, r
}