diff --git a/dynamic/handler.go b/dynamic/handler.go index b2b8a3b..54bded1 100644 --- a/dynamic/handler.go +++ b/dynamic/handler.go @@ -4,6 +4,7 @@ import ( "fmt" "reflect" + "git.xdrm.io/go/aicra/api" "git.xdrm.io/go/aicra/internal/config" ) @@ -38,7 +39,52 @@ func Build(fn HandlerFn, service config.Service) (*Handler, error) { return h, nil } -// Handle -func (h *Handler) Handle() { +// Handle binds input @data into HandleFn and returns map output +func (h *Handler) Handle(data map[string]interface{}) (map[string]interface{}, api.Error) { + fnv := reflect.ValueOf(h.fn) + callArgs := []reflect.Value{} + + // bind input data + if fnv.Type().NumIn() > 0 { + // create zero value struct + callStructPtr := reflect.New(fnv.Type().In(0)) + callStruct := callStructPtr.Elem() + + // set each field + for name := range h.spec.Input { + field := callStruct.FieldByName(name) + if !field.CanSet() { + continue + } + + // get value from @data + value, inData := data[name] + if !inData { + continue + } + field.Set(reflect.ValueOf(value).Convert(field.Type())) + } + callArgs = append(callArgs, callStruct) + } + + // call the HandlerFn + output := fnv.Call(callArgs) + + // no output OR pointer to output struct is nil + outdata := make(map[string]interface{}) + if len(h.spec.Output) < 1 || output[0].IsNil() { + return outdata, api.Error(output[len(output)-1].Int()) + } + + // extract struct from pointer + returnStruct := output[0].Elem() + + for name := range h.spec.Output { + field := returnStruct.FieldByName(name) + outdata[name] = field.Interface() + } + + // extract api.Error + return outdata, api.Error(output[len(output)-1].Int()) } diff --git a/http.go b/http.go index 8db6033..c131eb8 100644 --- a/http.go +++ b/http.go @@ -55,11 +55,11 @@ func (server httpServer) ServeHTTP(res http.ResponseWriter, req *http.Request) { } // 6. find a matching handler - var foundHandler *api.Handler + var foundHandler *handler var found bool for _, handler := range server.handlers { - if handler.GetMethod() == service.Method && handler.GetPath() == service.Pattern { + if handler.Method == service.Method && handler.Path == service.Pattern { foundHandler = handler found = true } @@ -91,9 +91,12 @@ func (server httpServer) ServeHTTP(res http.ResponseWriter, req *http.Request) { apireq.Param = dataset.Data // 10. execute - response := api.EmptyResponse() - apiErr := foundHandler.Fn(*apireq, response) - response.WithError(apiErr) + returned, apiErr := foundHandler.dynHandler.Handle(dataset.Data) + response := api.EmptyResponse().WithError(apiErr) + for key, value := range returned { + + response.SetData(name, value) + } // 11. apply headers res.Header().Set("Content-Type", "application/json; charset=utf-8")