implement the dynamic handler : fill input struct, do the call, fill return struct

This commit is contained in:
Adrien Marquès 2020-03-29 17:01:02 +02:00
parent a5424d8941
commit d7acf771ad
Signed by: xdrm-brackets
GPG Key ID: D75243CA236D825E
2 changed files with 56 additions and 7 deletions

View File

@ -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())
}

13
http.go
View File

@ -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")