Select Git revision
handler.go 3.25 KiB
package api
import (
"reflect"
"gitlab.com/uafrica/go-utils/errors"
)
type handler struct {
RequestParamsType reflect.Type
RequestBodyType reflect.Type
ResponseType reflect.Type
FuncValue reflect.Value
}
func NewHandler(fnc interface{}) (handler, error) {
h := handler{}
fncType := reflect.TypeOf(fnc)
if fncType.NumIn() < 2 || fncType.NumIn() > 3 {
return h, errors.Errorf("takes %d args instead of (Context, Params[, Body])", fncType.NumIn())
}
if fncType.NumOut() < 1 || fncType.NumOut() > 2 {
return h, errors.Errorf("returns %d results instead of ([Response,] error)", fncType.NumOut())
}
//arg[0] must implement interface lambda_helpers.Context
if _, ok := reflect.New(fncType.In(0)).Interface().(IContext); !ok {
return h, errors.Errorf("first arg %v does not implement lambda_helpers.IContext", fncType.In(0))
}
//arg[1] must be a struct for params. It may be an empty struct, but
//all public fields require a json tag which we will use to math the URL param name
if err := validateStructType(fncType.In(1)); err != nil {
return h, errors.Errorf("second arg %v is not valid params struct type", fncType.In(1))
}
h.RequestParamsType = fncType.In(1)
//arg[2] is optional and must be a struct for request body. It may be an empty struct, but
//all public fields require a json tag which we will use to unmarshal the request body from JSON
if fncType.NumIn() >= 3 {
if fncType.In(2).Kind() == reflect.Slice {
if err := validateStructType(fncType.In(2).Elem()); err != nil {
return h, errors.Errorf("third arg %v is not valid body []struct type", fncType.In(2))
}
} else {
if err := validateStructType(fncType.In(2)); err != nil {
return h, errors.Errorf("third arg %v is not valid body struct type", fncType.In(2))
}
}
//todo: check special fields for claims, and see if also applies to params struct...
//AccountID must be int64 or *int64 with tag =???
//UserID must be int64 or *int64 with tag =???
//Username must be string with tag =???
h.RequestBodyType = fncType.In(2)
}
//if 2 results, first must be response struct or array of response structs that will be marshalled to JSON
if fncType.NumOut() > 1 {
if fncType.Out(0).Kind() == reflect.Slice {
if err := validateStructType(fncType.Out(0).Elem()); err != nil {
return h, errors.Errorf("first result %v is not valid response []struct type", fncType.Out(0))
}
} else {
if err := validateStructType(fncType.Out(0)); err != nil {
return h, errors.Errorf("first result %v is not valid response struct type", fncType.Out(0))
}
}