From 87c15b91e51ce15a67bf84419114b507b068ebb0 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sun, 18 Apr 2021 16:49:24 +0200 Subject: [PATCH 1/5] feat: add middleware (Adapter) type --- api/adapter.go | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 api/adapter.go diff --git a/api/adapter.go b/api/adapter.go new file mode 100644 index 0000000..08a9959 --- /dev/null +++ b/api/adapter.go @@ -0,0 +1,6 @@ +package api + +import "net/http" + +// Adapter to encapsulate incoming requests +type Adapter func(http.HandlerFunc) http.HandlerFunc From 96164127e16c6fce584d40d0deb270a3e9b73d6a Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sun, 18 Apr 2021 16:49:46 +0200 Subject: [PATCH 2/5] feat: add Use() method to add adapters to the aicra builder --- builder.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/builder.go b/builder.go index 65c5240..f65fefa 100644 --- a/builder.go +++ b/builder.go @@ -5,6 +5,7 @@ import ( "io" "net/http" + "git.xdrm.io/go/aicra/api" "git.xdrm.io/go/aicra/datatype" "git.xdrm.io/go/aicra/internal/config" "git.xdrm.io/go/aicra/internal/dynfunc" @@ -14,6 +15,7 @@ import ( type Builder struct { conf *config.Server handlers []*apiHandler + adapters []api.Adapter } // represents an api handler (method-pattern combination) @@ -31,9 +33,23 @@ func (b *Builder) AddType(t datatype.T) { if b.conf.Services != nil { panic(errLateType) } + if b.conf.Types == nil { + b.conf.Types = make([]datatype.T, 0) + } b.conf.Types = append(b.conf.Types, t) } +// Use adds an http adapter (middleware) +func (b *Builder) Use(adapter api.Adapter) { + if b.conf == nil { + b.conf = &config.Server{} + } + if b.adapters == nil { + b.adapters = make([]api.Adapter, 0) + } + b.adapters = append(b.adapters, adapter) +} + // Setup the builder with its api definition file // panics if already setup func (b *Builder) Setup(r io.Reader) error { From 14ae59561cb5cf7e6b38fe4cf9036b899fc56407 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sun, 18 Apr 2021 16:50:02 +0200 Subject: [PATCH 3/5] feat: encapsulate request handling into adapters --- handler.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/handler.go b/handler.go index e85fe49..d91f086 100644 --- a/handler.go +++ b/handler.go @@ -12,8 +12,17 @@ import ( // Handler wraps the builder to handle requests type Handler Builder -// ServeHTTP implements http.Handler +// ServeHTTP implements http.Handler and wraps it in middlewares (adapters) func (s Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + var h = http.HandlerFunc(s.handleRequest) + + for _, adapter := range s.adapters { + h = adapter(h) + } + h(w, r) +} + +func (s Handler) handleRequest(w http.ResponseWriter, r *http.Request) { defer func() { if rc := recover(); rc != nil { log.Printf("recovering request: %s\n", rc) From 3986f7a02223701a6641a9ab4c8942bcd91cf017 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sun, 18 Apr 2021 17:53:53 +0200 Subject: [PATCH 4/5] fix: remove recoverer and body closer; must be users' responsability --- handler.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/handler.go b/handler.go index d91f086..b6feeb3 100644 --- a/handler.go +++ b/handler.go @@ -1,7 +1,6 @@ package aicra import ( - "log" "net/http" "git.xdrm.io/go/aicra/api" @@ -23,15 +22,6 @@ func (s Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } func (s Handler) handleRequest(w http.ResponseWriter, r *http.Request) { - defer func() { - if rc := recover(); rc != nil { - log.Printf("recovering request: %s\n", rc) - // try to send error response - api.EmptyResponse().WithError(api.ErrUncallableService).ServeHTTP(w, r) - } - }() - defer r.Body.Close() - // 1. find a matching service from config var service = s.conf.Find(r) if service == nil { From a693bbbf9b69c1cedd13022732bb8c5df17621ec Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sun, 18 Apr 2021 17:55:48 +0200 Subject: [PATCH 5/5] fix: reflect assign value to pointer of value in call argument --- internal/dynfunc/handler.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/internal/dynfunc/handler.go b/internal/dynfunc/handler.go index c12069c..4e36b71 100644 --- a/internal/dynfunc/handler.go +++ b/internal/dynfunc/handler.go @@ -2,6 +2,7 @@ package dynfunc import ( "fmt" + "log" "reflect" "git.xdrm.io/go/aicra/api" @@ -70,6 +71,29 @@ func (h *Handler) Handle(data map[string]interface{}) (map[string]interface{}, a if !inData { continue } + + var refvalue = reflect.ValueOf(value) + + // T to pointer of T + if field.Kind() == reflect.Ptr { + var ptrType = field.Type().Elem() + + if !refvalue.Type().ConvertibleTo(ptrType) { + log.Printf("Cannot convert %v into %v", refvalue.Type(), ptrType) + return nil, api.ErrUncallableService + } + + ptr := reflect.New(ptrType) + ptr.Elem().Set(reflect.ValueOf(value).Convert(ptrType)) + + field.Set(ptr) + continue + } + if !reflect.ValueOf(value).Type().ConvertibleTo(field.Type()) { + log.Printf("Cannot convert %v into %v", reflect.ValueOf(value).Type(), field.Type()) + return nil, api.ErrUncallableService + } + field.Set(reflect.ValueOf(value).Convert(field.Type())) } callArgs = append(callArgs, callStruct)