forked from Shiloh/githaven
105 lines
3.0 KiB
Go
105 lines
3.0 KiB
Go
|
// 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
|
||
|
}
|