Merge pull request 'feature: add http middleware capability' (#18) from feature/middleware into 0.3.0
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
commit
08b825b38f
|
@ -0,0 +1,6 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
// Adapter to encapsulate incoming requests
|
||||||
|
type Adapter func(http.HandlerFunc) http.HandlerFunc
|
16
builder.go
16
builder.go
|
@ -5,6 +5,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"git.xdrm.io/go/aicra/api"
|
||||||
"git.xdrm.io/go/aicra/datatype"
|
"git.xdrm.io/go/aicra/datatype"
|
||||||
"git.xdrm.io/go/aicra/internal/config"
|
"git.xdrm.io/go/aicra/internal/config"
|
||||||
"git.xdrm.io/go/aicra/internal/dynfunc"
|
"git.xdrm.io/go/aicra/internal/dynfunc"
|
||||||
|
@ -14,6 +15,7 @@ import (
|
||||||
type Builder struct {
|
type Builder struct {
|
||||||
conf *config.Server
|
conf *config.Server
|
||||||
handlers []*apiHandler
|
handlers []*apiHandler
|
||||||
|
adapters []api.Adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
// represents an api handler (method-pattern combination)
|
// represents an api handler (method-pattern combination)
|
||||||
|
@ -31,9 +33,23 @@ func (b *Builder) AddType(t datatype.T) {
|
||||||
if b.conf.Services != nil {
|
if b.conf.Services != nil {
|
||||||
panic(errLateType)
|
panic(errLateType)
|
||||||
}
|
}
|
||||||
|
if b.conf.Types == nil {
|
||||||
|
b.conf.Types = make([]datatype.T, 0)
|
||||||
|
}
|
||||||
b.conf.Types = append(b.conf.Types, t)
|
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
|
// Setup the builder with its api definition file
|
||||||
// panics if already setup
|
// panics if already setup
|
||||||
func (b *Builder) Setup(r io.Reader) error {
|
func (b *Builder) Setup(r io.Reader) error {
|
||||||
|
|
19
handler.go
19
handler.go
|
@ -1,7 +1,6 @@
|
||||||
package aicra
|
package aicra
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.xdrm.io/go/aicra/api"
|
"git.xdrm.io/go/aicra/api"
|
||||||
|
@ -12,17 +11,17 @@ import (
|
||||||
// Handler wraps the builder to handle requests
|
// Handler wraps the builder to handle requests
|
||||||
type Handler Builder
|
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) {
|
func (s Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
defer func() {
|
var h = http.HandlerFunc(s.handleRequest)
|
||||||
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()
|
|
||||||
|
|
||||||
|
for _, adapter := range s.adapters {
|
||||||
|
h = adapter(h)
|
||||||
|
}
|
||||||
|
h(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Handler) handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||||
// 1. find a matching service from config
|
// 1. find a matching service from config
|
||||||
var service = s.conf.Find(r)
|
var service = s.conf.Find(r)
|
||||||
if service == nil {
|
if service == nil {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package dynfunc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"git.xdrm.io/go/aicra/api"
|
"git.xdrm.io/go/aicra/api"
|
||||||
|
@ -70,6 +71,29 @@ func (h *Handler) Handle(data map[string]interface{}) (map[string]interface{}, a
|
||||||
if !inData {
|
if !inData {
|
||||||
continue
|
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()))
|
field.Set(reflect.ValueOf(value).Convert(field.Type()))
|
||||||
}
|
}
|
||||||
callArgs = append(callArgs, callStruct)
|
callArgs = append(callArgs, callStruct)
|
||||||
|
|
Loading…
Reference in New Issue