vendorify
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/context.go b/go/vendor/github.com/go-openapi/runtime/middleware/context.go
new file mode 100644
index 0000000..48d7150
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/context.go
@@ -0,0 +1,582 @@
+// Copyright 2015 go-swagger maintainers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package middleware
+
+import (
+ stdContext "context"
+ "net/http"
+ "strings"
+ "sync"
+
+ "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/logger"
+ "github.com/go-openapi/runtime/middleware/untyped"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+)
+
+// Debug when true turns on verbose logging
+var Debug = logger.DebugEnabled()
+var Logger logger.Logger = logger.StandardLogger{}
+
+func debugLog(format string, args ...interface{}) {
+ if Debug {
+ Logger.Printf(format, args...)
+ }
+}
+
+// A Builder can create middlewares
+type Builder func(http.Handler) http.Handler
+
+// PassthroughBuilder returns the handler, aka the builder identity function
+func PassthroughBuilder(handler http.Handler) http.Handler { return handler }
+
+// RequestBinder is an interface for types to implement
+// when they want to be able to bind from a request
+type RequestBinder interface {
+ BindRequest(*http.Request, *MatchedRoute) error
+}
+
+// Responder is an interface for types to implement
+// when they want to be considered for writing HTTP responses
+type Responder interface {
+ WriteResponse(http.ResponseWriter, runtime.Producer)
+}
+
+// ResponderFunc wraps a func as a Responder interface
+type ResponderFunc func(http.ResponseWriter, runtime.Producer)
+
+// WriteResponse writes to the response
+func (fn ResponderFunc) WriteResponse(rw http.ResponseWriter, pr runtime.Producer) {
+ fn(rw, pr)
+}
+
+// Context is a type safe wrapper around an untyped request context
+// 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
+}
+
+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) {
+ // lookup route info in the context
+ route, rCtx, _ := context.RouteInfo(r)
+ if rCtx != nil {
+ r = rCtx
+ }
+
+ // bind and validate the request using reflection
+ 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
+ }
+
+ // actually handle the request
+ result, err := oh.Handle(bound)
+ if err != nil {
+ // respond with failure
+ context.Respond(w, r, route.Produces, route, err)
+ return
+ }
+
+ // respond with success
+ 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
+}
+
+// NewRoutableContext creates a new context for a routable API
+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
+}
+
+// NewContext creates a new context wrapper
+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
+}
+
+// Serve serves the specified spec with the specified api registrations as a http.Handler
+func Serve(spec *loads.Document, api *untyped.API) http.Handler {
+ return ServeWithBuilder(spec, api, PassthroughBuilder)
+}
+
+// ServeWithBuilder serves the specified spec with the specified api registrations as a http.Handler that is decorated
+// by the Builder
+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
+)
+
+// MatchedRouteFrom request context value.
+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
+}
+
+// SecurityPrincipalFrom request context value.
+func SecurityPrincipalFrom(req *http.Request) interface{} {
+ return req.Context().Value(ctxSecurityPrincipal)
+}
+
+// SecurityScopesFrom request context value.
+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
+}
+
+// BasePath returns the base path for this API
+func (c *Context) BasePath() string {
+ return c.spec.BasePath()
+}
+
+// RequiredProduces returns the accepted content types for responses
+func (c *Context) RequiredProduces() []string {
+ return c.analyzer.RequiredProduces()
+}
+
+// BindValidRequest binds a params object to a request but only when the request is valid
+// 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
+
+ requestContentType := "*/*"
+ // check and validate content type, select consumer
+ 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
+ }
+ }
+ }
+ }
+
+ // check and validate the response format
+ if len(res) == 0 && runtime.HasBody(request) {
+ if str := NegotiateContentType(request, route.Produces, requestContentType); str == "" {
+ res = append(res, errors.InvalidResponseFormat(request.Header.Get(runtime.HeaderAccept), route.Produces))
+ }
+ }
+
+ // now bind the request with the provided binder
+ // it's assumed the binder will also validate the request and return an error if the
+ // request is invalid
+ 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
+}
+
+// ContentType gets the parsed value of a content type
+// Returns the media type, its charset and a shallow copy of the request
+// when its context doesn't contain the content type value, otherwise it returns
+// the same request
+// Returns the error that runtime.ContentType may retunrs.
+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
+}
+
+// LookupRoute looks a route up and returns true when it is found
+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
+}
+
+// RouteInfo tries to match a route for this request
+// Returns the matched route, a shallow copy of the request if its context
+// contains the matched router, otherwise the same request, and a bool to
+// indicate if it the request matches one of the routes, if it doesn't
+// then it returns false and nil for the other two return values
+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
+}
+
+// ResponseFormat negotiates the response content type
+// Returns the response format and a shallow copy of the request if its context
+// doesn't contain the response format, otherwise the same request
+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
+}
+
+// AllowedMethods gets the allowed methods for the path of this request
+func (c *Context) AllowedMethods(request *http.Request) []string {
+ return c.router.OtherMethods(request.Method, request.URL.EscapedPath())
+}
+
+// ResetAuth removes the current principal from the request context
+func (c *Context) ResetAuth(request *http.Request) *http.Request {
+ rctx := request.Context()
+ rctx = stdContext.WithValue(rctx, ctxSecurityPrincipal, nil)
+ rctx = stdContext.WithValue(rctx, ctxSecurityScopes, nil)
+ return request.WithContext(rctx)
+}
+
+// Authorize authorizes the request
+// Returns the principal object and a shallow copy of the request when its
+// context doesn't contain the principal, otherwise the same request or an error
+// (the last) if one of the authenticators returns one or an Unauthenticated error
+func (c *Context) Authorize(request *http.Request, route *MatchedRoute) (interface{}, *http.Request, error) {
+ if route == nil || !route.HasAuth() {
+ return nil, nil, nil
+ }
+
+ var rCtx = request.Context()
+ if v := rCtx.Value(ctxSecurityPrincipal); v != nil {
+ return v, request, nil
+ }
+
+ applies, usr, err := route.Authenticators.Authenticate(request, route)
+ if !applies || err != nil || !route.Authenticators.AllowsAnonymous() && usr == nil {
+ if err != nil {
+ return nil, nil, err
+ }
+ return nil, nil, errors.Unauthenticated("invalid credentials")
+ }
+ if route.Authorizer != nil {
+ if err := route.Authorizer.Authorize(request, usr); err != nil {
+ return nil, nil, errors.New(http.StatusForbidden, err.Error())
+ }
+ }
+
+ rCtx = stdContext.WithValue(rCtx, ctxSecurityPrincipal, usr)
+ rCtx = stdContext.WithValue(rCtx, ctxSecurityScopes, route.Authenticator.AllScopes())
+ return usr, request.WithContext(rCtx), nil
+}
+
+// BindAndValidate binds and validates the request
+// Returns the validation map and a shallow copy of the request when its context
+// doesn't contain the validation, otherwise it returns the same request or an
+// CompositeValidationError error
+func (c *Context) BindAndValidate(request *http.Request, matched *MatchedRoute) (interface{}, *http.Request, error) {
+ var rCtx = request.Context()
+
+ if v, ok := rCtx.Value(ctxBoundParams).(*validation); ok {
+ debugLog("got cached validation (valid: %t)", len(v.result) == 0)
+ if len(v.result) > 0 {
+ return v.bound, request, errors.CompositeValidationError(v.result...)
+ }
+ return v.bound, request, nil
+ }
+ result := validateRequest(c, request, matched)
+ rCtx = stdContext.WithValue(rCtx, ctxBoundParams, result)
+ request = request.WithContext(rCtx)
+ if len(result.result) > 0 {
+ return result.bound, request, errors.CompositeValidationError(result.result...)
+ }
+ debugLog("no validation errors found")
+ return result.bound, request, nil
+}
+
+// NotFound the default not found responder for when no route has been matched yet
+func (c *Context) NotFound(rw http.ResponseWriter, r *http.Request) {
+ c.Respond(rw, r, []string{c.api.DefaultProduces()}, nil, errors.NotFound("not found"))
+}
+
+// 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)
+ offers := []string{}
+ for _, mt := range produces {
+ if mt != c.api.DefaultProduces() {
+ offers = append(offers, mt)
+ }
+ }
+ // the default producer is last so more specific producers take precedence
+ offers = append(offers, c.api.DefaultProduces())
+ debugLog("offers: %v", offers)
+
+ var format string
+ format, r = c.ResponseFormat(r, offers)
+ rw.Header().Set(runtime.HeaderContentType, format)
+
+ if resp, ok := data.(Responder); ok {
+ producers := route.Producers
+ prod, ok := producers[format]
+ if !ok {
+ prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()}))
+ pr, ok := prods[c.api.DefaultProduces()]
+ if !ok {
+ panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format))
+ }
+ prod = pr
+ }
+ resp.WriteResponse(rw, prod)
+ return
+ }
+
+ if err, ok := data.(error); ok {
+ if format == "" {
+ rw.Header().Set(runtime.HeaderContentType, runtime.JSONMime)
+ }
+ if route == nil || route.Operation == nil {
+ c.api.ServeErrorFor("")(rw, r, err)
+ return
+ }
+ c.api.ServeErrorFor(route.Operation.ID)(rw, r, err)
+ return
+ }
+
+ if route == nil || route.Operation == nil {
+ rw.WriteHeader(200)
+ if r.Method == "HEAD" {
+ return
+ }
+ producers := c.api.ProducersFor(normalizeOffers(offers))
+ prod, ok := producers[format]
+ if !ok {
+ panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format))
+ }
+ if err := prod.Produce(rw, data); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ return
+ }
+
+ if _, code, ok := route.Operation.SuccessResponse(); ok {
+ rw.WriteHeader(code)
+ if code == 204 || r.Method == "HEAD" {
+ return
+ }
+
+ producers := route.Producers
+ prod, ok := producers[format]
+ if !ok {
+ if !ok {
+ prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()}))
+ pr, ok := prods[c.api.DefaultProduces()]
+ if !ok {
+ panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format))
+ }
+ prod = pr
+ }
+ }
+ if err := prod.Produce(rw, data); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ return
+ }
+
+ c.api.ServeErrorFor(route.Operation.ID)(rw, r, errors.New(http.StatusInternalServerError, "can't produce response"))
+}
+
+// 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
+ 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
+ }
+
+ redocOpts := RedocOpts{
+ BasePath: c.BasePath(),
+ Title: title,
+ }
+
+ return Spec("", c.spec.Raw(), Redoc(redocOpts, c.RoutesHandler(b)))
+}
+
+// RoutesHandler returns a handler to serve the API, just the routes and the contract defined in the swagger spec
+func (c *Context) RoutesHandler(builder Builder) http.Handler {
+ b := builder
+ if b == nil {
+ b = PassthroughBuilder
+ }
+ return NewRouter(c, b(NewOperationExecutor(c)))
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/denco/LICENSE b/go/vendor/github.com/go-openapi/runtime/middleware/denco/LICENSE
new file mode 100755
index 0000000..e65039a
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/denco/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Naoya Inada <naoina@kuune.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/denco/README.md b/go/vendor/github.com/go-openapi/runtime/middleware/denco/README.md
new file mode 100755
index 0000000..30109e1
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/denco/README.md
@@ -0,0 +1,180 @@
+# Denco [![Build Status](https://travis-ci.org/naoina/denco.png?branch=master)](https://travis-ci.org/naoina/denco)
+
+The fast and flexible HTTP request router for [Go](http://golang.org).
+
+Denco is based on Double-Array implementation of [Kocha-urlrouter](https://github.com/naoina/kocha-urlrouter).
+However, Denco is optimized and some features added.
+
+## Features
+
+* Fast (See [go-http-routing-benchmark](https://github.com/naoina/go-http-routing-benchmark))
+* [URL patterns](#url-patterns) (`/foo/:bar` and `/foo/*wildcard`)
+* Small (but enough) URL router API
+* HTTP request multiplexer like `http.ServeMux`
+
+## Installation
+
+ go get -u github.com/go-openapi/runtime/middleware/denco
+
+## Using as HTTP request multiplexer
+
+```go
+package main
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+
+ "github.com/go-openapi/runtime/middleware/denco"
+)
+
+func Index(w http.ResponseWriter, r *http.Request, params denco.Params) {
+ fmt.Fprintf(w, "Welcome to Denco!\n")
+}
+
+func User(w http.ResponseWriter, r *http.Request, params denco.Params) {
+ fmt.Fprintf(w, "Hello %s!\n", params.Get("name"))
+}
+
+func main() {
+ mux := denco.NewMux()
+ handler, err := mux.Build([]denco.Handler{
+ mux.GET("/", Index),
+ mux.GET("/user/:name", User),
+ mux.POST("/user/:name", User),
+ })
+ if err != nil {
+ panic(err)
+ }
+ log.Fatal(http.ListenAndServe(":8080", handler))
+}
+```
+
+## Using as URL router
+
+```go
+package main
+
+import (
+ "fmt"
+
+ "github.com/go-openapi/runtime/middleware/denco"
+)
+
+type route struct {
+ name string
+}
+
+func main() {
+ router := denco.New()
+ router.Build([]denco.Record{
+ {"/", &route{"root"}},
+ {"/user/:id", &route{"user"}},
+ {"/user/:name/:id", &route{"username"}},
+ {"/static/*filepath", &route{"static"}},
+ })
+
+ data, params, found := router.Lookup("/")
+ // print `&main.route{name:"root"}, denco.Params(nil), true`.
+ fmt.Printf("%#v, %#v, %#v\n", data, params, found)
+
+ data, params, found = router.Lookup("/user/hoge")
+ // print `&main.route{name:"user"}, denco.Params{denco.Param{Name:"id", Value:"hoge"}}, true`.
+ fmt.Printf("%#v, %#v, %#v\n", data, params, found)
+
+ data, params, found = router.Lookup("/user/hoge/7")
+ // print `&main.route{name:"username"}, denco.Params{denco.Param{Name:"name", Value:"hoge"}, denco.Param{Name:"id", Value:"7"}}, true`.
+ fmt.Printf("%#v, %#v, %#v\n", data, params, found)
+
+ data, params, found = router.Lookup("/static/path/to/file")
+ // print `&main.route{name:"static"}, denco.Params{denco.Param{Name:"filepath", Value:"path/to/file"}}, true`.
+ fmt.Printf("%#v, %#v, %#v\n", data, params, found)
+}
+```
+
+See [Godoc](http://godoc.org/github.com/go-openapi/runtime/middleware/denco) for more details.
+
+## Getting the value of path parameter
+
+You can get the value of path parameter by 2 ways.
+
+1. Using [`denco.Params.Get`](http://godoc.org/github.com/go-openapi/runtime/middleware/denco#Params.Get) method
+2. Find by loop
+
+```go
+package main
+
+import (
+ "fmt"
+
+ "github.com/go-openapi/runtime/middleware/denco"
+)
+
+func main() {
+ router := denco.New()
+ if err := router.Build([]denco.Record{
+ {"/user/:name/:id", "route1"},
+ }); err != nil {
+ panic(err)
+ }
+
+ // 1. Using denco.Params.Get method.
+ _, params, _ := router.Lookup("/user/alice/1")
+ name := params.Get("name")
+ if name != "" {
+ fmt.Printf("Hello %s.\n", name) // prints "Hello alice.".
+ }
+
+ // 2. Find by loop.
+ for _, param := range params {
+ if param.Name == "name" {
+ fmt.Printf("Hello %s.\n", name) // prints "Hello alice.".
+ }
+ }
+}
+```
+
+## URL patterns
+
+Denco's route matching strategy is "most nearly matching".
+
+When routes `/:name` and `/alice` have been built, URI `/alice` matches the route `/alice`, not `/:name`.
+Because URI `/alice` is more match with the route `/alice` than `/:name`.
+
+For more example, when routes below have been built:
+
+```
+/user/alice
+/user/:name
+/user/:name/:id
+/user/alice/:id
+/user/:id/bob
+```
+
+Routes matching are:
+
+```
+/user/alice => "/user/alice" (no match with "/user/:name")
+/user/bob => "/user/:name"
+/user/naoina/1 => "/user/:name/1"
+/user/alice/1 => "/user/alice/:id" (no match with "/user/:name/:id")
+/user/1/bob => "/user/:id/bob" (no match with "/user/:name/:id")
+/user/alice/bob => "/user/alice/:id" (no match with "/user/:name/:id" and "/user/:id/bob")
+```
+
+## Limitation
+
+Denco has some limitations below.
+
+* Number of param records (such as `/:name`) must be less than 2^22
+* Number of elements of internal slice must be less than 2^22
+
+## Benchmarks
+
+ cd $GOPATH/github.com/go-openapi/runtime/middleware/denco
+ go test -bench . -benchmem
+
+## License
+
+Denco is licensed under the MIT License.
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/denco/router.go b/go/vendor/github.com/go-openapi/runtime/middleware/denco/router.go
new file mode 100755
index 0000000..73703fd
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/denco/router.go
@@ -0,0 +1,452 @@
+// Package denco provides fast URL router.
+package denco
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+)
+
+const (
+ // ParamCharacter is a special character for path parameter.
+ ParamCharacter = ':'
+
+ // WildcardCharacter is a special character for wildcard path parameter.
+ WildcardCharacter = '*'
+
+ // TerminationCharacter is a special character for end of path.
+ TerminationCharacter = '#'
+
+ // MaxSize is max size of records and internal slice.
+ MaxSize = (1 << 22) - 1
+)
+
+// Router represents a URL router.
+type Router struct {
+ // 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.
+func New() *Router {
+ return &Router{
+ SizeHint: -1,
+ static: make(map[string]interface{}),
+ param: newDoubleArray(),
+ }
+}
+
+// Lookup returns data and path parameters that associated with path.
+// params is a slice of the Param that arranged in the order in which parameters appeared.
+// e.g. when built routing path is "/path/to/:id/:name" and given path is "/path/to/1/alice". params order is [{"id": "1"}, {"name": "alice"}], not [{"name": "alice"}, {"id": "1"}].
+func (rt *Router) Lookup(path string) (data interface{}, params Params, found bool) {
+ if data, found := rt.static[path]; found {
+ return data, nil, true
+ }
+ if len(rt.param.node) == 1 {
+ return nil, nil, false
+ }
+ nd, params, found := rt.param.lookup(path, make([]Param, 0, rt.SizeHint), 1)
+ if !found {
+ return nil, nil, false
+ }
+ for i := 0; i < len(params); i++ {
+ params[i].Name = nd.paramNames[i]
+ }
+ return nd.data, params, true
+}
+
+// Build builds URL router from records.
+func (rt *Router) Build(records []Record) error {
+ statics, params := makeRecords(records)
+ if len(params) > MaxSize {
+ return fmt.Errorf("denco: too many records")
+ }
+ if rt.SizeHint < 0 {
+ rt.SizeHint = 0
+ for _, p := range params {
+ size := 0
+ for _, k := range p.Key {
+ if k == ParamCharacter || k == WildcardCharacter {
+ size++
+ }
+ }
+ if size > rt.SizeHint {
+ rt.SizeHint = size
+ }
+ }
+ }
+ for _, r := range statics {
+ rt.static[r.Key] = r.Value
+ }
+ if err := rt.param.build(params, 1, 0, make(map[int]struct{})); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Param represents name and value of path parameter.
+type Param struct {
+ Name string
+ Value string
+}
+
+// Params represents the name and value of path parameters.
+type Params []Param
+
+// Get gets the first value associated with the given name.
+// If there are no values associated with the key, Get returns "".
+func (ps Params) Get(name string) string {
+ for _, p := range ps {
+ if p.Name == name {
+ return p.Value
+ }
+ }
+ return ""
+}
+
+type doubleArray struct {
+ bc []baseCheck
+ node []*node
+}
+
+func newDoubleArray() *doubleArray {
+ return &doubleArray{
+ bc: []baseCheck{0},
+ node: []*node{nil}, // A start index is adjusting to 1 because 0 will be used as a mark of non-existent node.
+ }
+}
+
+// baseCheck contains BASE, CHECK and Extra flags.
+// From the top, 22bits of BASE, 2bits of Extra flags and 8bits of CHECK.
+//
+// BASE (22bit) | Extra flags (2bit) | CHECK (8bit)
+// |----------------------|--|--------|
+// 32 10 8 0
+type baseCheck uint32
+
+func (bc baseCheck) Base() int {
+ return int(bc >> 10)
+}
+
+func (bc *baseCheck) SetBase(base int) {
+ *bc |= baseCheck(base) << 10
+}
+
+func (bc baseCheck) Check() byte {
+ return byte(bc)
+}
+
+func (bc *baseCheck) SetCheck(check byte) {
+ *bc |= baseCheck(check)
+}
+
+func (bc baseCheck) IsEmpty() bool {
+ return bc&0xfffffcff == 0
+}
+
+func (bc baseCheck) IsSingleParam() bool {
+ return bc¶mTypeSingle == paramTypeSingle
+}
+
+func (bc baseCheck) IsWildcardParam() bool {
+ return bc¶mTypeWildcard == paramTypeWildcard
+}
+
+func (bc baseCheck) IsAnyParam() bool {
+ return bc¶mTypeAny != 0
+}
+
+func (bc *baseCheck) SetSingleParam() {
+ *bc |= (1 << 8)
+}
+
+func (bc *baseCheck) SetWildcardParam() {
+ *bc |= (1 << 9)
+}
+
+const (
+ paramTypeSingle = 0x0100
+ paramTypeWildcard = 0x0200
+ paramTypeAny = 0x0300
+)
+
+func (da *doubleArray) lookup(path string, params []Param, idx int) (*node, []Param, bool) {
+ indices := make([]uint64, 0, 1)
+ for i := 0; i < len(path); i++ {
+ if da.bc[idx].IsAnyParam() {
+ indices = append(indices, (uint64(i)<<32)|(uint64(idx)&0xffffffff))
+ }
+ c := path[i]
+ if idx = nextIndex(da.bc[idx].Base(), c); idx >= len(da.bc) || da.bc[idx].Check() != c {
+ goto BACKTRACKING
+ }
+ }
+ 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)
+ if idx >= len(da.bc) {
+ break
+ }
+ next := NextSeparator(path, i)
+ params := append(params, Param{Value: path[i:next]})
+ if nd, params, found := da.lookup(path[next:], params, idx); found {
+ return nd, params, true
+ }
+ }
+ if da.bc[idx].IsWildcardParam() {
+ idx := nextIndex(da.bc[idx].Base(), WildcardCharacter)
+ params := append(params, Param{Value: path[i:]})
+ return da.node[da.bc[idx].Base()], params, true
+ }
+ }
+ return nil, nil, false
+}
+
+// build builds double-array from records.
+func (da *doubleArray) build(srcs []*record, idx, depth int, usedBase map[int]struct{}) error {
+ sort.Stable(recordSlice(srcs))
+ base, siblings, leaf, err := da.arrange(srcs, idx, depth, usedBase)
+ if err != nil {
+ return err
+ }
+ if leaf != nil {
+ nd, err := makeNode(leaf)
+ if err != nil {
+ return err
+ }
+ da.bc[idx].SetBase(len(da.node))
+ da.node = append(da.node, nd)
+ }
+ for _, sib := range siblings {
+ da.setCheck(nextIndex(base, sib.c), sib.c)
+ }
+ for _, sib := range siblings {
+ records := srcs[sib.start:sib.end]
+ switch sib.c {
+ case ParamCharacter:
+ for _, r := range records {
+ next := NextSeparator(r.Key, depth+1)
+ name := r.Key[depth+1 : next]
+ r.paramNames = append(r.paramNames, name)
+ r.Key = r.Key[next:]
+ }
+ da.bc[idx].SetSingleParam()
+ if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil {
+ return err
+ }
+ case WildcardCharacter:
+ r := records[0]
+ name := r.Key[depth+1 : len(r.Key)-1]
+ r.paramNames = append(r.paramNames, name)
+ r.Key = ""
+ da.bc[idx].SetWildcardParam()
+ if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil {
+ return err
+ }
+ default:
+ if err := da.build(records, nextIndex(base, sib.c), depth+1, usedBase); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// setBase sets BASE.
+func (da *doubleArray) setBase(i, base int) {
+ da.bc[i].SetBase(base)
+}
+
+// setCheck sets CHECK.
+func (da *doubleArray) setCheck(i int, check byte) {
+ da.bc[i].SetCheck(check)
+}
+
+// findEmptyIndex returns an index of unused BASE/CHECK node.
+func (da *doubleArray) findEmptyIndex(start int) int {
+ i := start
+ for ; i < len(da.bc); i++ {
+ if da.bc[i].IsEmpty() {
+ break
+ }
+ }
+ return i
+}
+
+// findBase returns good BASE.
+func (da *doubleArray) findBase(siblings []sibling, start int, usedBase map[int]struct{}) (base int) {
+ for idx, firstChar := start+1, siblings[0].c; ; idx = da.findEmptyIndex(idx + 1) {
+ base = nextIndex(idx, firstChar)
+ if _, used := usedBase[base]; used {
+ continue
+ }
+ i := 0
+ for ; i < len(siblings); i++ {
+ next := nextIndex(base, siblings[i].c)
+ if len(da.bc) <= next {
+ da.bc = append(da.bc, make([]baseCheck, next-len(da.bc)+1)...)
+ }
+ if !da.bc[next].IsEmpty() {
+ break
+ }
+ }
+ if i == len(siblings) {
+ break
+ }
+ }
+ usedBase[base] = struct{}{}
+ return base
+}
+
+func (da *doubleArray) arrange(records []*record, idx, depth int, usedBase map[int]struct{}) (base int, siblings []sibling, leaf *record, err error) {
+ siblings, leaf, err = makeSiblings(records, depth)
+ if err != nil {
+ return -1, nil, nil, err
+ }
+ if len(siblings) < 1 {
+ return -1, nil, leaf, nil
+ }
+ base = da.findBase(siblings, idx, usedBase)
+ if base > MaxSize {
+ return -1, nil, nil, fmt.Errorf("denco: too many elements of internal slice")
+ }
+ da.setBase(idx, base)
+ return base, siblings, leaf, err
+}
+
+// node represents a node of Double-Array.
+type node struct {
+ data interface{}
+
+ // Names of path parameters.
+ paramNames []string
+}
+
+// makeNode returns a new node from record.
+func makeNode(r *record) (*node, error) {
+ dups := make(map[string]bool)
+ for _, name := range r.paramNames {
+ if dups[name] {
+ return nil, fmt.Errorf("denco: path parameter `%v' is duplicated in the key `%v'", name, r.Key)
+ }
+ dups[name] = true
+ }
+ return &node{data: r.Value, paramNames: r.paramNames}, nil
+}
+
+// sibling represents an intermediate data of build for Double-Array.
+type sibling struct {
+ // An index of start of duplicated characters.
+ start int
+
+ // An index of end of duplicated characters.
+ end int
+
+ // A character of sibling.
+ c byte
+}
+
+// nextIndex returns a next index of array of BASE/CHECK.
+func nextIndex(base int, c byte) int {
+ return base ^ int(c)
+}
+
+// makeSiblings returns slice of sibling.
+func makeSiblings(records []*record, depth int) (sib []sibling, leaf *record, err error) {
+ var (
+ pc byte
+ n int
+ )
+ for i, r := range records {
+ if len(r.Key) <= depth {
+ leaf = r
+ continue
+ }
+ c := r.Key[depth]
+ switch {
+ case pc < c:
+ sib = append(sib, sibling{start: i, c: c})
+ case pc == c:
+ continue
+ default:
+ return nil, nil, fmt.Errorf("denco: BUG: routing table hasn't been sorted")
+ }
+ if n > 0 {
+ sib[n-1].end = i
+ }
+ pc = c
+ n++
+ }
+ if n == 0 {
+ return nil, leaf, nil
+ }
+ sib[n-1].end = len(records)
+ return sib, leaf, nil
+}
+
+// Record represents a record data for router construction.
+type Record struct {
+ // Key for router construction.
+ Key string
+
+ // Result value for Key.
+ Value interface{}
+}
+
+// NewRecord returns a new Record.
+func NewRecord(key string, value interface{}) Record {
+ return Record{
+ Key: key,
+ Value: value,
+ }
+}
+
+// record represents a record that use to build the Double-Array.
+type record struct {
+ Record
+ paramNames []string
+}
+
+// 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)
+ for _, r := range srcs {
+ if strings.ContainsAny(r.Key, spChars) {
+ r.Key += termChar
+ params = append(params, &record{Record: r})
+ } else {
+ statics = append(statics, &record{Record: r})
+ }
+ }
+ return statics, params
+}
+
+// recordSlice represents a slice of Record for sort and implements the sort.Interface.
+type recordSlice []*record
+
+// Len implements the sort.Interface.Len.
+func (rs recordSlice) Len() int {
+ return len(rs)
+}
+
+// Less implements the sort.Interface.Less.
+func (rs recordSlice) Less(i, j int) bool {
+ return rs[i].Key < rs[j].Key
+}
+
+// Swap implements the sort.Interface.Swap.
+func (rs recordSlice) Swap(i, j int) {
+ rs[i], rs[j] = rs[j], rs[i]
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/denco/server.go b/go/vendor/github.com/go-openapi/runtime/middleware/denco/server.go
new file mode 100755
index 0000000..0886713
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/denco/server.go
@@ -0,0 +1,106 @@
+package denco
+
+import (
+ "net/http"
+)
+
+// Mux represents a multiplexer for HTTP request.
+type Mux struct{}
+
+// NewMux returns a new Mux.
+func NewMux() *Mux {
+ return &Mux{}
+}
+
+// GET is shorthand of Mux.Handler("GET", path, handler).
+func (m *Mux) GET(path string, handler HandlerFunc) Handler {
+ return m.Handler("GET", path, handler)
+}
+
+// POST is shorthand of Mux.Handler("POST", path, handler).
+func (m *Mux) POST(path string, handler HandlerFunc) Handler {
+ return m.Handler("POST", path, handler)
+}
+
+// PUT is shorthand of Mux.Handler("PUT", path, handler).
+func (m *Mux) PUT(path string, handler HandlerFunc) Handler {
+ return m.Handler("PUT", path, handler)
+}
+
+// HEAD is shorthand of Mux.Handler("HEAD", path, handler).
+func (m *Mux) HEAD(path string, handler HandlerFunc) Handler {
+ return m.Handler("HEAD", path, handler)
+}
+
+// Handler returns a handler for HTTP method.
+func (m *Mux) Handler(method, path string, handler HandlerFunc) Handler {
+ return Handler{
+ Method: method,
+ Path: path,
+ Func: handler,
+ }
+}
+
+// Build builds a http.Handler.
+func (m *Mux) Build(handlers []Handler) (http.Handler, error) {
+ recordMap := make(map[string][]Record)
+ for _, h := range handlers {
+ recordMap[h.Method] = append(recordMap[h.Method], NewRecord(h.Path, h.Func))
+ }
+ mux := newServeMux()
+ for m, records := range recordMap {
+ router := New()
+ if err := router.Build(records); err != nil {
+ return nil, err
+ }
+ mux.routers[m] = router
+ }
+ return mux, nil
+}
+
+// Handler represents a handler of HTTP request.
+type Handler struct {
+ // Method is an HTTP method.
+ Method string
+
+ // Path is a routing path for handler.
+ Path string
+
+ // Func is a function of handler of HTTP request.
+ Func HandlerFunc
+}
+
+// The HandlerFunc type is aliased to type of handler function.
+type HandlerFunc func(w http.ResponseWriter, r *http.Request, params Params)
+
+type serveMux struct {
+ routers map[string]*Router
+}
+
+func newServeMux() *serveMux {
+ return &serveMux{
+ routers: make(map[string]*Router),
+ }
+}
+
+// ServeHTTP implements http.Handler interface.
+func (mux *serveMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ handler, params := mux.handler(r.Method, r.URL.Path)
+ handler(w, r, params)
+}
+
+func (mux *serveMux) handler(method, path string) (HandlerFunc, []Param) {
+ if router, found := mux.routers[method]; found {
+ if handler, params, found := router.Lookup(path); found {
+ return handler.(HandlerFunc), params
+ }
+ }
+ return NotFound, nil
+}
+
+// NotFound replies to the request with an HTTP 404 not found error.
+// NotFound is called when unknown HTTP method or a handler not found.
+// If you want to use the your own NotFound handler, please overwrite this variable.
+var NotFound = func(w http.ResponseWriter, r *http.Request, _ Params) {
+ http.NotFound(w, r)
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/denco/util.go b/go/vendor/github.com/go-openapi/runtime/middleware/denco/util.go
new file mode 100755
index 0000000..edc1f6a
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/denco/util.go
@@ -0,0 +1,12 @@
+package denco
+
+// NextSeparator returns an index of next separator in path.
+func NextSeparator(path string, start int) int {
+ for start < len(path) {
+ if c := path[start]; c == '/' || c == TerminationCharacter {
+ break
+ }
+ start++
+ }
+ return start
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/doc.go b/go/vendor/github.com/go-openapi/runtime/middleware/doc.go
new file mode 100644
index 0000000..eaf9060
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/doc.go
@@ -0,0 +1,62 @@
+// Copyright 2015 go-swagger maintainers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*Package middleware provides the library with helper functions for serving swagger APIs.
+
+Pseudo middleware handler
+
+ import (
+ "net/http"
+
+ "github.com/go-openapi/errors"
+ )
+
+ func newCompleteMiddleware(ctx *Context) http.Handler {
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ // use context to lookup routes
+ if matched, ok := ctx.RouteInfo(r); ok {
+
+ if matched.NeedsAuth() {
+ if _, err := ctx.Authorize(r, matched); err != nil {
+ ctx.Respond(rw, r, matched.Produces, matched, err)
+ return
+ }
+ }
+
+ bound, validation := ctx.BindAndValidate(r, matched)
+ if validation != nil {
+ ctx.Respond(rw, r, matched.Produces, matched, validation)
+ return
+ }
+
+ result, err := matched.Handler.Handle(bound)
+ if err != nil {
+ ctx.Respond(rw, r, matched.Produces, matched, err)
+ return
+ }
+
+ ctx.Respond(rw, r, matched.Produces, matched, result)
+ return
+ }
+
+ // Not found, check if it exists in the other methods first
+ if others := ctx.AllowedMethods(r); len(others) > 0 {
+ ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others))
+ return
+ }
+ ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.Path))
+ })
+ }
+*/
+package middleware
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/go18.go b/go/vendor/github.com/go-openapi/runtime/middleware/go18.go
new file mode 100644
index 0000000..75c762c
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/go18.go
@@ -0,0 +1,9 @@
+// +build go1.8
+
+package middleware
+
+import "net/url"
+
+func pathUnescape(path string) (string, error) {
+ return url.PathUnescape(path)
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/header/header.go b/go/vendor/github.com/go-openapi/runtime/middleware/header/header.go
new file mode 100644
index 0000000..3e34225
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/header/header.go
@@ -0,0 +1,326 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd.
+
+// this file was taken from the github.com/golang/gddo repository
+
+// Package header provides functions for parsing HTTP headers.
+package header
+
+import (
+ "net/http"
+ "strings"
+ "time"
+)
+
+// Octet types from RFC 2616.
+var octetTypes [256]octetType
+
+type octetType byte
+
+const (
+ isToken octetType = 1 << iota
+ isSpace
+)
+
+func init() {
+ // OCTET = <any 8-bit sequence of data>
+ // CHAR = <any US-ASCII character (octets 0 - 127)>
+ // CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
+ // CR = <US-ASCII CR, carriage return (13)>
+ // LF = <US-ASCII LF, linefeed (10)>
+ // SP = <US-ASCII SP, space (32)>
+ // HT = <US-ASCII HT, horizontal-tab (9)>
+ // <"> = <US-ASCII double-quote mark (34)>
+ // CRLF = CR LF
+ // LWS = [CRLF] 1*( SP | HT )
+ // TEXT = <any OCTET except CTLs, but including LWS>
+ // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <">
+ // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
+ // token = 1*<any CHAR except CTLs or separators>
+ // qdtext = <any TEXT except <">>
+
+ for c := 0; c < 256; c++ {
+ var t octetType
+ isCtl := c <= 31 || c == 127
+ isChar := 0 <= c && c <= 127
+ isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c))
+ if strings.ContainsRune(" \t\r\n", rune(c)) {
+ t |= isSpace
+ }
+ if isChar && !isCtl && !isSeparator {
+ t |= isToken
+ }
+ octetTypes[c] = t
+ }
+}
+
+// Copy returns a shallow copy of the header.
+func Copy(header http.Header) http.Header {
+ h := make(http.Header)
+ for k, vs := range header {
+ h[k] = vs
+ }
+ return h
+}
+
+var timeLayouts = []string{"Mon, 02 Jan 2006 15:04:05 GMT", time.RFC850, time.ANSIC}
+
+// ParseTime parses the header as time. The zero value is returned if the
+// header is not present or there is an error parsing the
+// header.
+func ParseTime(header http.Header, key string) time.Time {
+ if s := header.Get(key); s != "" {
+ for _, layout := range timeLayouts {
+ if t, err := time.Parse(layout, s); err == nil {
+ return t.UTC()
+ }
+ }
+ }
+ return time.Time{}
+}
+
+// ParseList parses a comma separated list of values. Commas are ignored in
+// quoted strings. Quoted values are not unescaped or unquoted. Whitespace is
+// trimmed.
+func ParseList(header http.Header, key string) []string {
+ var result []string
+ for _, s := range header[http.CanonicalHeaderKey(key)] {
+ begin := 0
+ end := 0
+ escape := false
+ quote := false
+ for i := 0; i < len(s); i++ {
+ b := s[i]
+ switch {
+ case escape:
+ escape = false
+ end = i + 1
+ case quote:
+ switch b {
+ case '\\':
+ escape = true
+ case '"':
+ quote = false
+ }
+ end = i + 1
+ case b == '"':
+ quote = true
+ end = i + 1
+ case octetTypes[b]&isSpace != 0:
+ if begin == end {
+ begin = i + 1
+ end = begin
+ }
+ case b == ',':
+ if begin < end {
+ result = append(result, s[begin:end])
+ }
+ begin = i + 1
+ end = begin
+ default:
+ end = i + 1
+ }
+ }
+ if begin < end {
+ result = append(result, s[begin:end])
+ }
+ }
+ return result
+}
+
+// ParseValueAndParams parses a comma separated list of values with optional
+// semicolon separated name-value pairs. Content-Type and Content-Disposition
+// headers are in this format.
+func ParseValueAndParams(header http.Header, key string) (string, map[string]string) {
+ return parseValueAndParams(header.Get(key))
+}
+
+func parseValueAndParams(s string) (value string, params map[string]string) {
+ params = make(map[string]string)
+ value, s = expectTokenSlash(s)
+ if value == "" {
+ return
+ }
+ value = strings.ToLower(value)
+ s = skipSpace(s)
+ for strings.HasPrefix(s, ";") {
+ var pkey string
+ pkey, s = expectToken(skipSpace(s[1:]))
+ if pkey == "" {
+ return
+ }
+ if !strings.HasPrefix(s, "=") {
+ return
+ }
+ var pvalue string
+ pvalue, s = expectTokenOrQuoted(s[1:])
+ if pvalue == "" {
+ return
+ }
+ pkey = strings.ToLower(pkey)
+ params[pkey] = pvalue
+ s = skipSpace(s)
+ }
+ return
+}
+
+// AcceptSpec ...
+type AcceptSpec struct {
+ Value string
+ Q float64
+}
+
+// ParseAccept2 ...
+func ParseAccept2(header http.Header, key string) (specs []AcceptSpec) {
+ for _, en := range ParseList(header, key) {
+ v, p := parseValueAndParams(en)
+ var spec AcceptSpec
+ spec.Value = v
+ spec.Q = 1.0
+ if p != nil {
+ if q, ok := p["q"]; ok {
+ spec.Q, _ = expectQuality(q)
+ }
+ }
+ if spec.Q < 0.0 {
+ continue
+ }
+ specs = append(specs, spec)
+ }
+
+ return
+}
+
+// ParseAccept parses Accept* headers.
+func ParseAccept(header http.Header, key string) (specs []AcceptSpec) {
+loop:
+ for _, s := range header[key] {
+ for {
+ var spec AcceptSpec
+ spec.Value, s = expectTokenSlash(s)
+ if spec.Value == "" {
+ continue loop
+ }
+ spec.Q = 1.0
+ s = skipSpace(s)
+ if strings.HasPrefix(s, ";") {
+ s = skipSpace(s[1:])
+ for !strings.HasPrefix(s, "q=") && s != "" && !strings.HasPrefix(s, ",") {
+ s = skipSpace(s[1:])
+ }
+ if strings.HasPrefix(s, "q=") {
+ spec.Q, s = expectQuality(s[2:])
+ if spec.Q < 0.0 {
+ continue loop
+ }
+ }
+ }
+ specs = append(specs, spec)
+ s = skipSpace(s)
+ if !strings.HasPrefix(s, ",") {
+ continue loop
+ }
+ s = skipSpace(s[1:])
+ }
+ }
+ return
+}
+
+func skipSpace(s string) (rest string) {
+ i := 0
+ for ; i < len(s); i++ {
+ if octetTypes[s[i]]&isSpace == 0 {
+ break
+ }
+ }
+ return s[i:]
+}
+
+func expectToken(s string) (token, rest string) {
+ i := 0
+ for ; i < len(s); i++ {
+ if octetTypes[s[i]]&isToken == 0 {
+ break
+ }
+ }
+ return s[:i], s[i:]
+}
+
+func expectTokenSlash(s string) (token, rest string) {
+ i := 0
+ for ; i < len(s); i++ {
+ b := s[i]
+ if (octetTypes[b]&isToken == 0) && b != '/' {
+ break
+ }
+ }
+ return s[:i], s[i:]
+}
+
+func expectQuality(s string) (q float64, rest string) {
+ switch {
+ case len(s) == 0:
+ return -1, ""
+ case s[0] == '0':
+ q = 0
+ case s[0] == '1':
+ q = 1
+ default:
+ return -1, ""
+ }
+ s = s[1:]
+ if !strings.HasPrefix(s, ".") {
+ return q, s
+ }
+ s = s[1:]
+ i := 0
+ n := 0
+ d := 1
+ for ; i < len(s); i++ {
+ b := s[i]
+ if b < '0' || b > '9' {
+ break
+ }
+ n = n*10 + int(b) - '0'
+ d *= 10
+ }
+ return q + float64(n)/float64(d), s[i:]
+}
+
+func expectTokenOrQuoted(s string) (value string, rest string) {
+ if !strings.HasPrefix(s, "\"") {
+ return expectToken(s)
+ }
+ s = s[1:]
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ case '"':
+ return s[:i], s[i+1:]
+ case '\\':
+ p := make([]byte, len(s)-1)
+ j := copy(p, s[:i])
+ escape := true
+ for i = i + 1; i < len(s); i++ {
+ b := s[i]
+ switch {
+ case escape:
+ escape = false
+ p[j] = b
+ j++
+ case b == '\\':
+ escape = true
+ case b == '"':
+ return string(p[:j]), s[i+1:]
+ default:
+ p[j] = b
+ j++
+ }
+ }
+ return "", ""
+ }
+ }
+ return "", ""
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/negotiate.go b/go/vendor/github.com/go-openapi/runtime/middleware/negotiate.go
new file mode 100644
index 0000000..a9b6f27
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/negotiate.go
@@ -0,0 +1,98 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd.
+
+// this file was taken from the github.com/golang/gddo repository
+
+package middleware
+
+import (
+ "net/http"
+ "strings"
+
+ "github.com/go-openapi/runtime/middleware/header"
+)
+
+// NegotiateContentEncoding returns the best offered content encoding for the
+// request's Accept-Encoding header. If two offers match with equal weight and
+// then the offer earlier in the list is preferred. If no offers are
+// acceptable, then "" is returned.
+func NegotiateContentEncoding(r *http.Request, offers []string) string {
+ bestOffer := "identity"
+ bestQ := -1.0
+ specs := header.ParseAccept(r.Header, "Accept-Encoding")
+ for _, offer := range offers {
+ for _, spec := range specs {
+ if spec.Q > bestQ &&
+ (spec.Value == "*" || spec.Value == offer) {
+ bestQ = spec.Q
+ bestOffer = offer
+ }
+ }
+ }
+ if bestQ == 0 {
+ bestOffer = ""
+ }
+ return bestOffer
+}
+
+// NegotiateContentType returns the best offered content type for the request's
+// Accept header. If two offers match with equal weight, then the more specific
+// offer is preferred. For example, text/* trumps */*. If two offers match
+// with equal weight and specificity, then the offer earlier in the list is
+// preferred. If no offers match, then defaultOffer is returned.
+func NegotiateContentType(r *http.Request, offers []string, defaultOffer string) string {
+ bestOffer := defaultOffer
+ bestQ := -1.0
+ bestWild := 3
+ specs := header.ParseAccept(r.Header, "Accept")
+ for _, rawOffer := range offers {
+ offer := normalizeOffer(rawOffer)
+ // No Accept header: just return the first offer.
+ if len(specs) == 0 {
+ return rawOffer
+ }
+ for _, spec := range specs {
+ switch {
+ case spec.Q == 0.0:
+ // ignore
+ case spec.Q < bestQ:
+ // better match found
+ case spec.Value == "*/*":
+ if spec.Q > bestQ || bestWild > 2 {
+ bestQ = spec.Q
+ bestWild = 2
+ bestOffer = rawOffer
+ }
+ case strings.HasSuffix(spec.Value, "/*"):
+ if strings.HasPrefix(offer, spec.Value[:len(spec.Value)-1]) &&
+ (spec.Q > bestQ || bestWild > 1) {
+ bestQ = spec.Q
+ bestWild = 1
+ bestOffer = rawOffer
+ }
+ default:
+ if spec.Value == offer &&
+ (spec.Q > bestQ || bestWild > 0) {
+ bestQ = spec.Q
+ bestWild = 0
+ bestOffer = rawOffer
+ }
+ }
+ }
+ }
+ return bestOffer
+}
+
+func normalizeOffers(orig []string) (norm []string) {
+ for _, o := range orig {
+ norm = append(norm, normalizeOffer(o))
+ }
+ return
+}
+
+func normalizeOffer(orig string) string {
+ return strings.SplitN(orig, ";", 2)[0]
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go b/go/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go
new file mode 100644
index 0000000..466f553
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go
@@ -0,0 +1,48 @@
+// Copyright 2015 go-swagger maintainers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package middleware
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime"
+)
+
+type errorResp struct {
+ code int
+ response interface{}
+ headers http.Header
+}
+
+func (e *errorResp) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+ for k, v := range e.headers {
+ for _, val := range v {
+ rw.Header().Add(k, val)
+ }
+ }
+ if e.code > 0 {
+ rw.WriteHeader(e.code)
+ } else {
+ rw.WriteHeader(http.StatusInternalServerError)
+ }
+ if err := producer.Produce(rw, e.response); err != nil {
+ panic(err)
+ }
+}
+
+// NotImplemented the error response when the response is not implemented
+func NotImplemented(message string) Responder {
+ return &errorResp{http.StatusNotImplemented, message, make(http.Header)}
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/operation.go b/go/vendor/github.com/go-openapi/runtime/middleware/operation.go
new file mode 100644
index 0000000..1175a63
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/operation.go
@@ -0,0 +1,30 @@
+// Copyright 2015 go-swagger maintainers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package middleware
+
+import "net/http"
+
+// NewOperationExecutor creates a context aware middleware that handles the operations after routing
+func NewOperationExecutor(ctx *Context) http.Handler {
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ // use context to lookup routes
+ route, rCtx, _ := ctx.RouteInfo(r)
+ if rCtx != nil {
+ r = rCtx
+ }
+
+ route.Handler.ServeHTTP(rw, r)
+ })
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/parameter.go b/go/vendor/github.com/go-openapi/runtime/middleware/parameter.go
new file mode 100644
index 0000000..8975b6e
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/parameter.go
@@ -0,0 +1,480 @@
+// Copyright 2015 go-swagger maintainers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package middleware
+
+import (
+ "encoding"
+ "encoding/base64"
+ "fmt"
+ "io"
+ "net/http"
+ "reflect"
+ "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"
+)
+
+const defaultMaxMemory = 32 << 20
+
+var textUnmarshalType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
+
+func newUntypedParamBinder(param spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *untypedParamBinder {
+ binder := new(untypedParamBinder)
+ binder.Name = param.Name
+ binder.parameter = ¶m
+ binder.formats = formats
+ if param.In != "body" {
+ binder.validator = validate.NewParamValidator(¶m, formats)
+ } else {
+ binder.validator = validate.NewSchemaValidator(param.Schema, spec, param.Name, formats)
+ }
+
+ return binder
+}
+
+type untypedParamBinder struct {
+ parameter *spec.Parameter
+ formats strfmt.Registry
+ Name string
+ validator validate.EntityValidator
+}
+
+func (p *untypedParamBinder) Type() reflect.Type {
+ return p.typeForSchema(p.parameter.Type, p.parameter.Format, p.parameter.Items)
+}
+
+func (p *untypedParamBinder) typeForSchema(tpe, format string, items *spec.Items) reflect.Type {
+ switch tpe {
+ case "boolean":
+ return reflect.TypeOf(true)
+
+ case "string":
+ if tt, ok := p.formats.GetType(format); ok {
+ return tt
+ }
+ return reflect.TypeOf("")
+
+ case "integer":
+ switch format {
+ case "int8":
+ return reflect.TypeOf(int8(0))
+ case "int16":
+ return reflect.TypeOf(int16(0))
+ case "int32":
+ return reflect.TypeOf(int32(0))
+ case "int64":
+ return reflect.TypeOf(int64(0))
+ default:
+ return reflect.TypeOf(int64(0))
+ }
+
+ case "number":
+ switch format {
+ case "float":
+ return reflect.TypeOf(float32(0))
+ case "double":
+ return reflect.TypeOf(float64(0))
+ }
+
+ case "array":
+ if items == nil {
+ return nil
+ }
+ itemsType := p.typeForSchema(items.Type, items.Format, items.Items)
+ if itemsType == nil {
+ return nil
+ }
+ return reflect.MakeSlice(reflect.SliceOf(itemsType), 0, 0).Type()
+
+ case "file":
+ return reflect.TypeOf(&runtime.File{}).Elem()
+
+ case "object":
+ return reflect.TypeOf(map[string]interface{}{})
+ }
+ return nil
+}
+
+func (p *untypedParamBinder) allowsMulti() bool {
+ return p.parameter.In == "query" || p.parameter.In == "formData"
+}
+
+func (p *untypedParamBinder) readValue(values runtime.Gettable, target reflect.Value) ([]string, bool, bool, error) {
+ name, in, cf, tpe := p.parameter.Name, p.parameter.In, p.parameter.CollectionFormat, p.parameter.Type
+ if tpe == "array" {
+ if cf == "multi" {
+ if !p.allowsMulti() {
+ return nil, false, false, errors.InvalidCollectionFormat(name, in, cf)
+ }
+ vv, hasKey, _ := values.GetOK(name)
+ return vv, false, hasKey, nil
+ }
+
+ v, hk, hv := values.GetOK(name)
+ if !hv {
+ return nil, false, hk, nil
+ }
+ d, c, e := p.readFormattedSliceFieldValue(v[len(v)-1], target)
+ return d, c, hk, e
+ }
+
+ vv, hk, _ := values.GetOK(name)
+ return vv, false, hk, nil
+}
+
+func (p *untypedParamBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, target reflect.Value) error {
+ // fmt.Println("binding", p.name, "as", p.Type())
+ switch p.parameter.In {
+ case "query":
+ data, custom, hasKey, err := p.readValue(runtime.Values(request.URL.Query()), target)
+ if err != nil {
+ return err
+ }
+ if custom {
+ return nil
+ }
+
+ return p.bindValue(data, hasKey, target)
+
+ case "header":
+ data, custom, hasKey, err := p.readValue(runtime.Values(request.Header), target)
+ if err != nil {
+ return err
+ }
+ if custom {
+ return nil
+ }
+ return p.bindValue(data, hasKey, target)
+
+ case "path":
+ data, custom, hasKey, err := p.readValue(routeParams, target)
+ if err != nil {
+ return err
+ }
+ if custom {
+ return nil
+ }
+ return p.bindValue(data, hasKey, target)
+
+ case "formData":
+ var err error
+ var mt string
+
+ mt, _, e := runtime.ContentType(request.Header)
+ if e != nil {
+ // because of the interface conversion go thinks the error is not nil
+ // so we first check for nil and then set the err var if it's not nil
+ err = e
+ }
+
+ if err != nil {
+ return errors.InvalidContentType("", []string{"multipart/form-data", "application/x-www-form-urlencoded"})
+ }
+
+ if mt != "multipart/form-data" && mt != "application/x-www-form-urlencoded" {
+ return errors.InvalidContentType(mt, []string{"multipart/form-data", "application/x-www-form-urlencoded"})
+ }
+
+ if mt == "multipart/form-data" {
+ if err = request.ParseMultipartForm(defaultMaxMemory); err != nil {
+ return errors.NewParseError(p.Name, p.parameter.In, "", err)
+ }
+ }
+
+ if err = request.ParseForm(); err != nil {
+ return errors.NewParseError(p.Name, p.parameter.In, "", err)
+ }
+
+ if p.parameter.Type == "file" {
+ file, header, ffErr := request.FormFile(p.parameter.Name)
+ if ffErr != nil {
+ return errors.NewParseError(p.Name, p.parameter.In, "", ffErr)
+ }
+ target.Set(reflect.ValueOf(runtime.File{Data: file, Header: header}))
+ return nil
+ }
+
+ if request.MultipartForm != nil {
+ data, custom, hasKey, rvErr := p.readValue(runtime.Values(request.MultipartForm.Value), target)
+ if rvErr != nil {
+ return rvErr
+ }
+ if custom {
+ return nil
+ }
+ return p.bindValue(data, hasKey, target)
+ }
+ data, custom, hasKey, err := p.readValue(runtime.Values(request.PostForm), target)
+ if err != nil {
+ return err
+ }
+ if custom {
+ return nil
+ }
+ return p.bindValue(data, hasKey, target)
+
+ case "body":
+ newValue := reflect.New(target.Type())
+ if !runtime.HasBody(request) {
+ if p.parameter.Default != nil {
+ target.Set(reflect.ValueOf(p.parameter.Default))
+ }
+
+ return nil
+ }
+ if err := consumer.Consume(request.Body, newValue.Interface()); err != nil {
+ if err == io.EOF && p.parameter.Default != nil {
+ target.Set(reflect.ValueOf(p.parameter.Default))
+ return nil
+ }
+ tpe := p.parameter.Type
+ if p.parameter.Format != "" {
+ tpe = p.parameter.Format
+ }
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, nil)
+ }
+ target.Set(reflect.Indirect(newValue))
+ return nil
+ default:
+ return errors.New(500, fmt.Sprintf("invalid parameter location %q", p.parameter.In))
+ }
+}
+
+func (p *untypedParamBinder) bindValue(data []string, hasKey bool, target reflect.Value) error {
+ if p.parameter.Type == "array" {
+ return p.setSliceFieldValue(target, p.parameter.Default, data, hasKey)
+ }
+ var d string
+ if len(data) > 0 {
+ d = data[len(data)-1]
+ }
+ return p.setFieldValue(target, p.parameter.Default, d, hasKey)
+}
+
+func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue interface{}, data string, hasKey bool) error {
+ tpe := p.parameter.Type
+ if p.parameter.Format != "" {
+ tpe = p.parameter.Format
+ }
+
+ if (!hasKey || (!p.parameter.AllowEmptyValue && data == "")) && p.parameter.Required && p.parameter.Default == nil {
+ return errors.Required(p.Name, p.parameter.In)
+ }
+
+ ok, err := p.tryUnmarshaler(target, defaultValue, data)
+ if err != nil {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if ok {
+ return nil
+ }
+
+ defVal := reflect.Zero(target.Type())
+ if defaultValue != nil {
+ defVal = reflect.ValueOf(defaultValue)
+ }
+
+ if tpe == "byte" {
+ if data == "" {
+ if target.CanSet() {
+ target.SetBytes(defVal.Bytes())
+ }
+ return nil
+ }
+
+ b, err := base64.StdEncoding.DecodeString(data)
+ if err != nil {
+ b, err = base64.URLEncoding.DecodeString(data)
+ if err != nil {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ }
+ if target.CanSet() {
+ target.SetBytes(b)
+ }
+ return nil
+ }
+
+ switch target.Kind() {
+ case reflect.Bool:
+ if data == "" {
+ if target.CanSet() {
+ target.SetBool(defVal.Bool())
+ }
+ return nil
+ }
+ b, err := swag.ConvertBool(data)
+ if err != nil {
+ return err
+ }
+ if target.CanSet() {
+ target.SetBool(b)
+ }
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ if data == "" {
+ if target.CanSet() {
+ rd := defVal.Convert(reflect.TypeOf(int64(0)))
+ target.SetInt(rd.Int())
+ }
+ return nil
+ }
+ i, err := strconv.ParseInt(data, 10, 64)
+ if err != nil {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if target.OverflowInt(i) {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if target.CanSet() {
+ target.SetInt(i)
+ }
+
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ if data == "" {
+ if target.CanSet() {
+ rd := defVal.Convert(reflect.TypeOf(uint64(0)))
+ target.SetUint(rd.Uint())
+ }
+ return nil
+ }
+ u, err := strconv.ParseUint(data, 10, 64)
+ if err != nil {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if target.OverflowUint(u) {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if target.CanSet() {
+ target.SetUint(u)
+ }
+
+ case reflect.Float32, reflect.Float64:
+ if data == "" {
+ if target.CanSet() {
+ rd := defVal.Convert(reflect.TypeOf(float64(0)))
+ target.SetFloat(rd.Float())
+ }
+ return nil
+ }
+ f, err := strconv.ParseFloat(data, 64)
+ if err != nil {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if target.OverflowFloat(f) {
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ if target.CanSet() {
+ target.SetFloat(f)
+ }
+
+ case reflect.String:
+ value := data
+ if value == "" {
+ value = defVal.String()
+ }
+ // validate string
+ if target.CanSet() {
+ target.SetString(value)
+ }
+
+ case reflect.Ptr:
+ if data == "" && defVal.Kind() == reflect.Ptr {
+ if target.CanSet() {
+ target.Set(defVal)
+ }
+ return nil
+ }
+ newVal := reflect.New(target.Type().Elem())
+ if err := p.setFieldValue(reflect.Indirect(newVal), defVal, data, hasKey); err != nil {
+ return err
+ }
+ if target.CanSet() {
+ target.Set(newVal)
+ }
+
+ default:
+ return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
+ }
+ return nil
+}
+
+func (p *untypedParamBinder) tryUnmarshaler(target reflect.Value, defaultValue interface{}, data string) (bool, error) {
+ if !target.CanSet() {
+ return false, nil
+ }
+ // When a type implements encoding.TextUnmarshaler we'll use that instead of reflecting some more
+ if reflect.PtrTo(target.Type()).Implements(textUnmarshalType) {
+ if defaultValue != nil && len(data) == 0 {
+ target.Set(reflect.ValueOf(defaultValue))
+ return true, nil
+ }
+ value := reflect.New(target.Type())
+ if err := value.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(data)); err != nil {
+ return true, err
+ }
+ target.Set(reflect.Indirect(value))
+ return true, nil
+ }
+ return false, nil
+}
+
+func (p *untypedParamBinder) readFormattedSliceFieldValue(data string, target reflect.Value) ([]string, bool, error) {
+ ok, err := p.tryUnmarshaler(target, p.parameter.Default, data)
+ if err != nil {
+ return nil, true, err
+ }
+ if ok {
+ return nil, true, nil
+ }
+
+ return swag.SplitByFormat(data, p.parameter.CollectionFormat), false, nil
+}
+
+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)
+ }
+
+ defVal := reflect.Zero(target.Type())
+ if defaultValue != nil {
+ defVal = reflect.ValueOf(defaultValue)
+ }
+
+ if !target.CanSet() {
+ return nil
+ }
+ if sz == 0 {
+ target.Set(defVal)
+ return nil
+ }
+
+ value := reflect.MakeSlice(reflect.SliceOf(target.Type().Elem()), sz, sz)
+
+ for i := 0; i < sz; i++ {
+ if err := p.setFieldValue(value.Index(i), nil, data[i], hasKey); err != nil {
+ return err
+ }
+ }
+
+ target.Set(value)
+
+ return nil
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/pre_go18.go b/go/vendor/github.com/go-openapi/runtime/middleware/pre_go18.go
new file mode 100644
index 0000000..0338525
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/pre_go18.go
@@ -0,0 +1,9 @@
+// +build !go1.8
+
+package middleware
+
+import "net/url"
+
+func pathUnescape(path string) (string, error) {
+ return url.QueryUnescape(path)
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/redoc.go b/go/vendor/github.com/go-openapi/runtime/middleware/redoc.go
new file mode 100644
index 0000000..2127794
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/redoc.go
@@ -0,0 +1,101 @@
+package middleware
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "net/http"
+ "path"
+)
+
+// RedocOpts configures the Redoc middlewares
+type RedocOpts 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
+ // RedocURL for the js that generates the redoc site, defaults to: https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js
+ RedocURL string
+ // Title for the documentation site, default to: API documentation
+ Title string
+}
+
+// EnsureDefaults in case some options are missing
+func (r *RedocOpts) EnsureDefaults() {
+ if r.BasePath == "" {
+ r.BasePath = "/"
+ }
+ if r.Path == "" {
+ r.Path = "docs"
+ }
+ if r.SpecURL == "" {
+ r.SpecURL = "/swagger.json"
+ }
+ if r.RedocURL == "" {
+ r.RedocURL = redocLatest
+ }
+ if r.Title == "" {
+ r.Title = "API documentation"
+ }
+}
+
+// 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))
+
+ 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 (
+ redocLatest = "https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js"
+ redocTemplate = `<!DOCTYPE html>
+<html>
+ <head>
+ <title>{{ .Title }}</title>
+ <!-- needed for adaptive design -->
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <!--
+ ReDoc doesn't change outer page styles
+ -->
+ <style>
+ body {
+ margin: 0;
+ padding: 0;
+ }
+ </style>
+ </head>
+ <body>
+ <redoc spec-url='{{ .SpecURL }}'></redoc>
+ <script src="{{ .RedocURL }}"> </script>
+ </body>
+</html>
+`
+)
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/request.go b/go/vendor/github.com/go-openapi/runtime/middleware/request.go
new file mode 100644
index 0000000..ee725f5
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/request.go
@@ -0,0 +1,104 @@
+// Copyright 2015 go-swagger maintainers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package middleware
+
+import (
+ "net/http"
+ "reflect"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+)
+
+// RequestBinder 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 {
+ binders := make(map[string]*untypedParamBinder)
+ for fieldName, param := range parameters {
+ binders[fieldName] = newUntypedParamBinder(param, spec, formats)
+ }
+ return &untypedRequestBinder{
+ Parameters: parameters,
+ paramBinders: binders,
+ Spec: spec,
+ Formats: formats,
+ }
+}
+
+// Bind perform the databinding and validation
+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
+ debugLog("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())
+ var target reflect.Value
+ if !isMap {
+ binder.Name = fieldName
+ target = val.FieldByName(fieldName)
+ }
+
+ if isMap {
+ tpe := binder.Type()
+ if tpe == nil {
+ if param.Schema.Type.Contains("array") {
+ tpe = reflect.TypeOf([]interface{}{})
+ } else {
+ tpe = reflect.TypeOf(map[string]interface{}{})
+ }
+ }
+ target = reflect.Indirect(reflect.New(tpe))
+
+ }
+
+ if !target.IsValid() {
+ result = append(result, errors.New(500, "parameter name %q is an unknown field", binder.Name))
+ continue
+ }
+
+ if err := binder.Bind(request, routeParams, consumer, target); err != nil {
+ result = append(result, err)
+ continue
+ }
+
+ if binder.validator != nil {
+ rr := binder.validator.Validate(target.Interface())
+ if rr != nil && rr.HasErrors() {
+ result = append(result, rr.AsError())
+ }
+ }
+
+ if isMap {
+ val.SetMapIndex(reflect.ValueOf(param.Name), target)
+ }
+ }
+
+ if len(result) > 0 {
+ return errors.CompositeValidationError(result...)
+ }
+
+ return nil
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/router.go b/go/vendor/github.com/go-openapi/runtime/middleware/router.go
new file mode 100644
index 0000000..73c8eeb
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/router.go
@@ -0,0 +1,478 @@
+// Copyright 2015 go-swagger maintainers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package middleware
+
+import (
+ "fmt"
+ "net/http"
+ fpath "path"
+ "regexp"
+ "strings"
+
+ "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/runtime"
+ "github.com/go-openapi/runtime/middleware/denco"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+)
+
+// RouteParam is a object to capture route params in a framework agnostic way.
+// implementations of the muxer should use these route params to communicate with the
+// swagger framework
+type RouteParam struct {
+ Name string
+ Value string
+}
+
+// RouteParams the collection of route params
+type RouteParams []RouteParam
+
+// Get gets the value for the route param for the specified key
+func (r RouteParams) Get(name string) string {
+ vv, _, _ := r.GetOK(name)
+ if len(vv) > 0 {
+ return vv[len(vv)-1]
+ }
+ return ""
+}
+
+// GetOK gets the value but also returns booleans to indicate if a key or value
+// is present. This aids in validation and satisfies an interface in use there
+//
+// The returned values are: data, has key, has value
+func (r RouteParams) GetOK(name string) ([]string, bool, bool) {
+ for _, p := range r {
+ if p.Name == name {
+ return []string{p.Value}, true, p.Value != ""
+ }
+ }
+ return nil, false, false
+}
+
+// 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)
+ }
+
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ if _, rCtx, ok := ctx.RouteInfo(r); ok {
+ next.ServeHTTP(rw, rCtx)
+ return
+ }
+
+ // Not found, check if it exists in the other methods first
+ if others := ctx.AllowedMethods(r); len(others) > 0 {
+ ctx.Respond(rw, r, ctx.analyzer.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others))
+ return
+ }
+
+ ctx.Respond(rw, r, ctx.analyzer.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.EscapedPath()))
+ })
+}
+
+// RoutableAPI represents an interface for things that can serve
+// as a provider of implementations for the swagger router
+type RoutableAPI interface {
+ HandlerFor(string, string) (http.Handler, bool)
+ ServeErrorFor(string) func(http.ResponseWriter, *http.Request, error)
+ ConsumersFor([]string) map[string]runtime.Consumer
+ ProducersFor([]string) map[string]runtime.Producer
+ AuthenticatorsFor(map[string]spec.SecurityScheme) map[string]runtime.Authenticator
+ Authorizer() runtime.Authorizer
+ Formats() strfmt.Registry
+ DefaultProduces() string
+ DefaultConsumes() string
+}
+
+// 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
+}
+
+type defaultRouter struct {
+ spec *loads.Document
+ routers map[string]*denco.Router
+}
+
+func newDefaultRouteBuilder(spec *loads.Document, api RoutableAPI) *defaultRouteBuilder {
+ return &defaultRouteBuilder{
+ spec: spec,
+ analyzer: analysis.New(spec.Spec()),
+ api: api,
+ records: make(map[string][]denco.Record),
+ }
+}
+
+// DefaultRouter creates a default implemenation of the router
+func DefaultRouter(spec *loads.Document, api RoutableAPI) Router {
+ builder := newDefaultRouteBuilder(spec, api)
+ 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.AddRoute(method, fp, operation)
+ }
+ }
+ }
+ return builder.Build()
+}
+
+// RouteAuthenticator is an authenticator that can compose several authenticators together.
+// It also knows when it contains an authenticator that allows for anonymous pass through.
+// Contains a group of 1 or more authenticators that have a logical AND relationship
+type RouteAuthenticator struct {
+ Authenticator map[string]runtime.Authenticator
+ Schemes []string
+ Scopes map[string][]string
+ allScopes []string
+ commonScopes []string
+ allowAnonymous bool
+}
+
+func (ra *RouteAuthenticator) AllowsAnonymous() bool {
+ return ra.allowAnonymous
+}
+
+// AllScopes returns a list of unique scopes that is the combination
+// of all the scopes in the requirements
+func (ra *RouteAuthenticator) AllScopes() []string {
+ return ra.allScopes
+}
+
+// CommonScopes returns a list of unique scopes that are common in all the
+// scopes in the requirements
+func (ra *RouteAuthenticator) CommonScopes() []string {
+ return ra.commonScopes
+}
+
+// Authenticate Authenticator interface implementation
+func (ra *RouteAuthenticator) Authenticate(req *http.Request, route *MatchedRoute) (bool, interface{}, error) {
+ if ra.allowAnonymous {
+ route.Authenticator = ra
+ return true, nil, nil
+ }
+ // iterate in proper order
+ var lastResult interface{}
+ for _, scheme := range ra.Schemes {
+ if authenticator, ok := ra.Authenticator[scheme]; ok {
+ applies, princ, err := authenticator.Authenticate(&security.ScopedAuthRequest{
+ Request: req,
+ RequiredScopes: ra.Scopes[scheme],
+ })
+ if !applies {
+ return false, nil, nil
+ }
+
+ if err != nil {
+ route.Authenticator = ra
+ return true, nil, err
+ }
+ lastResult = princ
+ }
+ }
+ route.Authenticator = ra
+ return true, lastResult, nil
+}
+
+func stringSliceUnion(slices ...[]string) []string {
+ unique := make(map[string]struct{})
+ var result []string
+ for _, slice := range slices {
+ for _, entry := range slice {
+ if _, ok := unique[entry]; ok {
+ continue
+ }
+ unique[entry] = struct{}{}
+ result = append(result, entry)
+ }
+ }
+ return result
+}
+
+func stringSliceIntersection(slices ...[]string) []string {
+ unique := make(map[string]int)
+ var intersection []string
+
+ total := len(slices)
+ var emptyCnt int
+ for _, slice := range slices {
+ if len(slice) == 0 {
+ emptyCnt++
+ continue
+ }
+
+ for _, entry := range slice {
+ unique[entry]++
+ if unique[entry] == total-emptyCnt { // this entry appeared in all the non-empty slices
+ intersection = append(intersection, entry)
+ }
+ }
+ }
+
+ return intersection
+}
+
+// RouteAuthenticators represents a group of authenticators that represent a logical OR
+type RouteAuthenticators []RouteAuthenticator
+
+// AllowsAnonymous returns true when there is an authenticator that means optional auth
+func (ras RouteAuthenticators) AllowsAnonymous() bool {
+ for _, ra := range ras {
+ if ra.AllowsAnonymous() {
+ return true
+ }
+ }
+ return false
+}
+
+// Authenticate method implemention so this collection can be used as authenticator
+func (ras RouteAuthenticators) Authenticate(req *http.Request, route *MatchedRoute) (bool, interface{}, error) {
+ var lastError error
+ var allowsAnon bool
+ var anonAuth RouteAuthenticator
+
+ for _, ra := range ras {
+ if ra.AllowsAnonymous() {
+ anonAuth = ra
+ allowsAnon = true
+ continue
+ }
+ applies, usr, err := ra.Authenticate(req, route)
+ if !applies || err != nil || usr == nil {
+ if err != nil {
+ lastError = err
+ }
+ continue
+ }
+ return applies, usr, nil
+ }
+
+ if allowsAnon && lastError == nil {
+ route.Authenticator = &anonAuth
+ return true, nil, lastError
+ }
+ return lastError != nil, nil, lastError
+}
+
+type routeEntry struct {
+ PathPattern string
+ BasePath string
+ Operation *spec.Operation
+ Consumes []string
+ Consumers map[string]runtime.Consumer
+ Produces []string
+ Producers map[string]runtime.Producer
+ Parameters map[string]spec.Parameter
+ Handler http.Handler
+ Formats strfmt.Registry
+ Binder *untypedRequestBinder
+ Authenticators RouteAuthenticators
+ Authorizer runtime.Authorizer
+}
+
+// MatchedRoute represents the route that was matched in this request
+type MatchedRoute struct {
+ routeEntry
+ Params RouteParams
+ Consumer runtime.Consumer
+ Producer runtime.Producer
+ Authenticator *RouteAuthenticator
+}
+
+// HasAuth returns true when the route has a security requirement defined
+func (m *MatchedRoute) HasAuth() bool {
+ return len(m.Authenticators) > 0
+}
+
+// NeedsAuth returns true when the request still
+// needs to perform authentication
+func (m *MatchedRoute) NeedsAuth() bool {
+ return m.HasAuth() && m.Authenticator == nil
+}
+
+func (d *defaultRouter) Lookup(method, path string) (*MatchedRoute, bool) {
+ mth := strings.ToUpper(method)
+ debugLog("looking up route for %s %s", method, path)
+ if Debug {
+ if len(d.routers) == 0 {
+ debugLog("there are no known routers")
+ }
+ for meth := range d.routers {
+ debugLog("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))
+ var params RouteParams
+ for _, p := range rp {
+ v, err := pathUnescape(p.Value)
+ if err != nil {
+ debugLog("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
+ // check if this parameter is a fragment within a path segment
+ if xpos := strings.Index(entry.PathPattern, fmt.Sprintf("{%s}", p.Name)) + len(p.Name) + 2; xpos < len(entry.PathPattern) && entry.PathPattern[xpos] != '/' {
+ // extract fragment parameters
+ ep := strings.Split(entry.PathPattern[xpos:], "/")[0]
+ pnames, pvalues := decodeCompositParams(p.Name, v, ep, nil, nil)
+ for i, pname := range pnames {
+ params = append(params, RouteParam{Name: pname, Value: pvalues[i]})
+ }
+ } else {
+ // use the parameter directly
+ params = append(params, RouteParam{Name: p.Name, Value: v})
+ }
+ }
+ return &MatchedRoute{routeEntry: *entry, Params: params}, true
+ }
+ } else {
+ debugLog("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)
+ }
+ return nil, false
+}
+
+func (d *defaultRouter) OtherMethods(method, path string) []string {
+ mn := strings.ToUpper(method)
+ var methods []string
+ for k, v := range d.routers {
+ if k != mn {
+ if _, _, ok := v.Lookup(fpath.Clean(path)); ok {
+ methods = append(methods, k)
+ continue
+ }
+ }
+ }
+ return methods
+}
+
+// convert swagger parameters per path segment into a denco parameter as multiple parameters per segment are not supported in denco
+var pathConverter = regexp.MustCompile(`{(.+?)}([^/]*)`)
+
+func decodeCompositParams(name string, value string, pattern string, names []string, values []string) ([]string, []string) {
+ pleft := strings.Index(pattern, "{")
+ names = append(names, name)
+ if pleft < 0 {
+ if strings.HasSuffix(value, pattern) {
+ values = append(values, value[:len(value)-len(pattern)])
+ } else {
+ values = append(values, "")
+ }
+ } else {
+ toskip := pattern[:pleft]
+ pright := strings.Index(pattern, "}")
+ vright := strings.Index(value, toskip)
+ if vright >= 0 {
+ values = append(values, value[:vright])
+ } else {
+ values = append(values, "")
+ value = ""
+ }
+ return decodeCompositParams(pattern[pleft+1:pright], value[vright+len(toskip):], pattern[pright+1:], names, values)
+ }
+ return names, values
+}
+
+func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Operation) {
+ mn := strings.ToUpper(method)
+
+ bp := fpath.Clean(d.spec.BasePath())
+ if len(bp) > 0 && bp[len(bp)-1] == '/' {
+ bp = bp[:len(bp)-1]
+ }
+
+ debugLog("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)
+ parameters := d.analyzer.ParamsFor(method, strings.TrimPrefix(path, bp))
+
+ record := denco.NewRecord(pathConverter.ReplaceAllString(path, ":$1"), &routeEntry{
+ BasePath: bp,
+ PathPattern: path,
+ Operation: operation,
+ Handler: handler,
+ Consumes: consumes,
+ Produces: produces,
+ Consumers: d.api.ConsumersFor(normalizeOffers(consumes)),
+ Producers: d.api.ProducersFor(normalizeOffers(produces)),
+ Parameters: parameters,
+ Formats: d.api.Formats(),
+ Binder: newUntypedRequestBinder(parameters, d.spec.Spec(), d.api.Formats()),
+ Authenticators: d.buildAuthenticators(operation),
+ Authorizer: d.api.Authorizer(),
+ })
+ d.records[mn] = append(d.records[mn], record)
+ }
+}
+
+func (d *defaultRouteBuilder) buildAuthenticators(operation *spec.Operation) RouteAuthenticators {
+ requirements := d.analyzer.SecurityRequirementsFor(operation)
+ var auths []RouteAuthenticator
+ for _, reqs := range requirements {
+ var schemes []string
+ scopes := make(map[string][]string, len(reqs))
+ var scopeSlices [][]string
+ for _, req := range reqs {
+ schemes = append(schemes, req.Name)
+ scopes[req.Name] = req.Scopes
+ scopeSlices = append(scopeSlices, req.Scopes)
+ }
+
+ definitions := d.analyzer.SecurityDefinitionsForRequirements(reqs)
+ authenticators := d.api.AuthenticatorsFor(definitions)
+ auths = append(auths, RouteAuthenticator{
+ Authenticator: authenticators,
+ Schemes: schemes,
+ Scopes: scopes,
+ allScopes: stringSliceUnion(scopeSlices...),
+ commonScopes: stringSliceIntersection(scopeSlices...),
+ allowAnonymous: len(reqs) == 1 && reqs[0].Name == "",
+ })
+ }
+ return auths
+}
+
+func (d *defaultRouteBuilder) Build() *defaultRouter {
+ routers := make(map[string]*denco.Router)
+ for method, records := range d.records {
+ router := denco.New()
+ _ = router.Build(records)
+ routers[method] = router
+ }
+ return &defaultRouter{
+ spec: d.spec,
+ routers: routers,
+ }
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/security.go b/go/vendor/github.com/go-openapi/runtime/middleware/security.go
new file mode 100644
index 0000000..2b061ca
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/security.go
@@ -0,0 +1,39 @@
+// Copyright 2015 go-swagger maintainers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package middleware
+
+import "net/http"
+
+func newSecureAPI(ctx *Context, next http.Handler) http.Handler {
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ route, rCtx, _ := ctx.RouteInfo(r)
+ if rCtx != nil {
+ r = rCtx
+ }
+ if route != nil && !route.NeedsAuth() {
+ next.ServeHTTP(rw, r)
+ return
+ }
+
+ _, rCtx, err := ctx.Authorize(r, route)
+ if err != nil {
+ ctx.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+ r = rCtx
+
+ next.ServeHTTP(rw, r)
+ })
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/spec.go b/go/vendor/github.com/go-openapi/runtime/middleware/spec.go
new file mode 100644
index 0000000..6e02b83
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/spec.go
@@ -0,0 +1,48 @@
+// Copyright 2015 go-swagger maintainers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package middleware
+
+import (
+ "net/http"
+ "path"
+)
+
+// Spec creates a middleware to serve a swagger spec.
+// 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 {
+ if basePath == "" {
+ basePath = "/"
+ }
+ pth := path.Join(basePath, "swagger.json")
+
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ if r.URL.Path == pth {
+ rw.Header().Set("Content-Type", "application/json")
+ rw.WriteHeader(http.StatusOK)
+ //#nosec
+ rw.Write(b)
+ return
+ }
+
+ if next == nil {
+ rw.Header().Set("Content-Type", "application/json")
+ rw.WriteHeader(http.StatusNotFound)
+ return
+ }
+ next.ServeHTTP(rw, r)
+ })
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go b/go/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go
new file mode 100644
index 0000000..3b0cd4e
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go
@@ -0,0 +1,286 @@
+// Copyright 2015 go-swagger maintainers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package untyped
+
+import (
+ "fmt"
+ "net/http"
+ "sort"
+ "strings"
+
+ "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"
+)
+
+// NewAPI creates the default untyped API
+func NewAPI(spec *loads.Document) *API {
+ var an *analysis.Spec
+ if spec != nil && spec.Spec() != nil {
+ an = analysis.New(spec.Spec())
+ }
+ api := &API{
+ spec: spec,
+ analyzer: an,
+ consumers: make(map[string]runtime.Consumer, 10),
+ producers: make(map[string]runtime.Producer, 10),
+ authenticators: make(map[string]runtime.Authenticator),
+ operations: make(map[string]map[string]runtime.OperationHandler),
+ ServeError: errors.ServeError,
+ Models: make(map[string]func() interface{}),
+ formats: strfmt.NewFormats(),
+ }
+ return api.WithJSONDefaults()
+}
+
+// API represents an untyped mux for a swagger spec
+type API struct {
+ spec *loads.Document
+ analyzer *analysis.Spec
+ DefaultProduces string
+ DefaultConsumes string
+ consumers map[string]runtime.Consumer
+ producers map[string]runtime.Producer
+ authenticators map[string]runtime.Authenticator
+ authorizer runtime.Authorizer
+ operations map[string]map[string]runtime.OperationHandler
+ ServeError func(http.ResponseWriter, *http.Request, error)
+ Models map[string]func() interface{}
+ formats strfmt.Registry
+}
+
+// WithJSONDefaults loads the json defaults for this api
+func (d *API) WithJSONDefaults() *API {
+ d.DefaultConsumes = runtime.JSONMime
+ d.DefaultProduces = runtime.JSONMime
+ d.consumers[runtime.JSONMime] = runtime.JSONConsumer()
+ d.producers[runtime.JSONMime] = runtime.JSONProducer()
+ return d
+}
+
+// WithoutJSONDefaults clears the json defaults for this api
+func (d *API) WithoutJSONDefaults() *API {
+ d.DefaultConsumes = ""
+ d.DefaultProduces = ""
+ delete(d.consumers, runtime.JSONMime)
+ delete(d.producers, runtime.JSONMime)
+ return d
+}
+
+// Formats returns the registered string formats
+func (d *API) Formats() strfmt.Registry {
+ if d.formats == nil {
+ d.formats = strfmt.NewFormats()
+ }
+ return d.formats
+}
+
+// RegisterFormat registers a custom format validator
+func (d *API) RegisterFormat(name string, format strfmt.Format, validator strfmt.Validator) {
+ if d.formats == nil {
+ d.formats = strfmt.NewFormats()
+ }
+ d.formats.Add(name, format, validator)
+}
+
+// RegisterAuth registers an auth handler in this api
+func (d *API) RegisterAuth(scheme string, handler runtime.Authenticator) {
+ if d.authenticators == nil {
+ d.authenticators = make(map[string]runtime.Authenticator)
+ }
+ d.authenticators[scheme] = handler
+}
+
+// RegisterAuthorizer registers an authorizer handler in this api
+func (d *API) RegisterAuthorizer(handler runtime.Authorizer) {
+ d.authorizer = handler
+}
+
+// RegisterConsumer registers a consumer for a media type.
+func (d *API) RegisterConsumer(mediaType string, handler runtime.Consumer) {
+ if d.consumers == nil {
+ d.consumers = make(map[string]runtime.Consumer, 10)
+ }
+ d.consumers[strings.ToLower(mediaType)] = handler
+}
+
+// RegisterProducer registers a producer for a media type
+func (d *API) RegisterProducer(mediaType string, handler runtime.Producer) {
+ if d.producers == nil {
+ d.producers = make(map[string]runtime.Producer, 10)
+ }
+ d.producers[strings.ToLower(mediaType)] = handler
+}
+
+// RegisterOperation registers an operation handler for an operation name
+func (d *API) RegisterOperation(method, path string, handler runtime.OperationHandler) {
+ if d.operations == nil {
+ d.operations = make(map[string]map[string]runtime.OperationHandler, 30)
+ }
+ um := strings.ToUpper(method)
+ if b, ok := d.operations[um]; !ok || b == nil {
+ d.operations[um] = make(map[string]runtime.OperationHandler)
+ }
+ d.operations[um][path] = handler
+}
+
+// OperationHandlerFor returns the operation handler for the specified id if it can be found
+func (d *API) OperationHandlerFor(method, path string) (runtime.OperationHandler, bool) {
+ if d.operations == nil {
+ return nil, false
+ }
+ if pi, ok := d.operations[strings.ToUpper(method)]; ok {
+ h, ok := pi[path]
+ return h, ok
+ }
+ return nil, false
+}
+
+// ConsumersFor gets the consumers for the specified media types
+func (d *API) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
+ result := make(map[string]runtime.Consumer)
+ for _, mt := range mediaTypes {
+ if consumer, ok := d.consumers[mt]; ok {
+ result[mt] = consumer
+ }
+ }
+ return result
+}
+
+// ProducersFor gets the producers for the specified media types
+func (d *API) ProducersFor(mediaTypes []string) map[string]runtime.Producer {
+ result := make(map[string]runtime.Producer)
+ for _, mt := range mediaTypes {
+ if producer, ok := d.producers[mt]; ok {
+ result[mt] = producer
+ }
+ }
+ return result
+}
+
+// AuthenticatorsFor gets the authenticators for the specified security schemes
+func (d *API) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator {
+ result := make(map[string]runtime.Authenticator)
+ for k := range schemes {
+ if a, ok := d.authenticators[k]; ok {
+ result[k] = a
+ }
+ }
+ return result
+}
+
+// AuthorizersFor returns the registered authorizer
+func (d *API) Authorizer() runtime.Authorizer {
+ return d.authorizer
+}
+
+// Validate validates this API for any missing items
+func (d *API) Validate() error {
+ return d.validate()
+}
+
+// validateWith validates the registrations in this API against the provided spec analyzer
+func (d *API) validate() error {
+ var consumes []string
+ for k := range d.consumers {
+ consumes = append(consumes, k)
+ }
+
+ var produces []string
+ for k := range d.producers {
+ produces = append(produces, k)
+ }
+
+ var authenticators []string
+ for k := range d.authenticators {
+ authenticators = append(authenticators, k)
+ }
+
+ var operations []string
+ for m, v := range d.operations {
+ for p := range v {
+ operations = append(operations, fmt.Sprintf("%s %s", strings.ToUpper(m), p))
+ }
+ }
+
+ var definedAuths []string
+ for k := range d.spec.Spec().SecurityDefinitions {
+ definedAuths = append(definedAuths, k)
+ }
+
+ if err := d.verify("consumes", consumes, d.analyzer.RequiredConsumes()); err != nil {
+ return err
+ }
+ if err := d.verify("produces", produces, d.analyzer.RequiredProduces()); err != nil {
+ return err
+ }
+ if err := d.verify("operation", operations, d.analyzer.OperationMethodPaths()); err != nil {
+ return err
+ }
+
+ requiredAuths := d.analyzer.RequiredSecuritySchemes()
+ if err := d.verify("auth scheme", authenticators, requiredAuths); err != nil {
+ return err
+ }
+ if err := d.verify("security definitions", definedAuths, requiredAuths); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (d *API) verify(name string, registrations []string, expectations []string) error {
+
+ sort.Sort(sort.StringSlice(registrations))
+ sort.Sort(sort.StringSlice(expectations))
+
+ expected := map[string]struct{}{}
+ seen := map[string]struct{}{}
+
+ for _, v := range expectations {
+ expected[v] = struct{}{}
+ }
+
+ var unspecified []string
+ for _, v := range registrations {
+ seen[v] = struct{}{}
+ if _, ok := expected[v]; !ok {
+ unspecified = append(unspecified, v)
+ }
+ }
+
+ for k := range seen {
+ delete(expected, k)
+ }
+
+ var unregistered []string
+ for k := range expected {
+ unregistered = append(unregistered, k)
+ }
+ sort.Sort(sort.StringSlice(unspecified))
+ sort.Sort(sort.StringSlice(unregistered))
+
+ if len(unregistered) > 0 || len(unspecified) > 0 {
+ return &errors.APIVerificationFailed{
+ Section: name,
+ MissingSpecification: unspecified,
+ MissingRegistration: unregistered,
+ }
+ }
+
+ return nil
+}
diff --git a/go/vendor/github.com/go-openapi/runtime/middleware/validation.go b/go/vendor/github.com/go-openapi/runtime/middleware/validation.go
new file mode 100644
index 0000000..bb8df3c
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/runtime/middleware/validation.go
@@ -0,0 +1,122 @@
+// Copyright 2015 go-swagger maintainers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package middleware
+
+import (
+ "mime"
+ "net/http"
+ "strings"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/swag"
+)
+
+type validation struct {
+ context *Context
+ result []error
+ request *http.Request
+ route *MatchedRoute
+ bound map[string]interface{}
+}
+
+// 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
+ }
+ mt, _, err := mime.ParseMediaType(actual)
+ if err != nil {
+ return errors.InvalidContentType(actual, allowed)
+ }
+ if swag.ContainsStringsCI(allowed, mt) {
+ return nil
+ }
+ if swag.ContainsStringsCI(allowed, "*/*") {
+ return nil
+ }
+ parts := strings.Split(actual, "/")
+ if len(parts) == 2 && swag.ContainsStringsCI(allowed, parts[0]+"/*") {
+ return nil
+ }
+ return errors.InvalidContentType(actual, allowed)
+}
+
+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.contentType()
+ if len(validate.result) == 0 {
+ validate.responseFormat()
+ }
+ if len(validate.result) == 0 {
+ validate.parameters()
+ }
+
+ return validate
+}
+
+func (v *validation) parameters() {
+ debugLog("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{}) {
+ v.result = append(v.result, e.(error))
+ }
+ return
+ }
+ v.result = append(v.result, result)
+ }
+}
+
+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())
+ ct, _, req, err := v.context.ContentType(v.request)
+ if err != nil {
+ v.result = append(v.result, err)
+ } else {
+ v.request = req
+ }
+
+ if len(v.result) == 0 {
+ if err := validateContentType(v.route.Consumes, ct); err != nil {
+ v.result = append(v.result, err)
+ }
+ }
+ if ct != "" && v.route.Consumer == nil {
+ cons, ok := v.route.Consumers[ct]
+ if !ok {
+ v.result = append(v.result, errors.New(500, "no consumer registered for %s", ct))
+ } else {
+ v.route.Consumer = cons
+ }
+ }
+ }
+}
+
+func (v *validation) responseFormat() {
+ if str, rCtx := v.context.ResponseFormat(v.request, v.route.Produces); str == "" && runtime.HasBody(v.request) {
+ v.request = rCtx
+ v.result = append(v.result, errors.InvalidResponseFormat(v.request.Header.Get(runtime.HeaderAccept), v.route.Produces))
+ }
+}