Skip to content
Snippets Groups Projects
Select Git revision
  • 9cd8cc8a5a97344d90d30c3b3ebad842e5ccf9f3
  • main default protected
  • v1.298.0
  • v1.297.0
  • v1.296.0
  • v1.295.0
  • v1.294.0
  • v1.293.0
  • v1.292.0
  • v1.291.0
  • v1.290.0
  • v1.289.0
  • v1.288.0
  • v1.287.0
  • v1.286.0
  • v1.285.0
  • v1.284.0
  • v1.283.0
  • v1.282.0
  • v1.281.0
  • v1.280.0
  • v1.279.0
22 results

handler.go

Blame
  • 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))
    			}
    		}