diff --git a/server.go b/server.go index e8245d2..2cef02e 100644 --- a/server.go +++ b/server.go @@ -20,6 +20,7 @@ import ( "sync/atomic" "syscall" "time" + "unsafe" "repositories.action2quare.com/ayo/gocommon/flagx" "repositories.action2quare.com/ayo/gocommon/logger" @@ -606,3 +607,68 @@ func MakeHttpRequestForLogging(r *http.Request) *http.Request { r.Body = ib return r } + +type apiFuncType func(http.ResponseWriter, *http.Request) +type HttpApiReceiver struct { + methods map[string]apiFuncType +} + +func MakeHttpApiReceiver[T any](receiver *T) HttpApiReceiver { + methods := make(map[string]apiFuncType) + + tp := reflect.TypeOf(receiver) + name := tp.Elem().Name() + for i := 0; i < tp.NumMethod(); i++ { + method := tp.Method(i) + if method.Type.NumIn() != 3 { + continue + } + + if method.Type.In(0) != tp { + continue + } + + var w http.ResponseWriter + if method.Type.In(1) != reflect.TypeOf(w) { + continue + } + + var r http.Request + if method.Type.In(2) != reflect.TypeOf(&r) { + continue + } + + if method.Name == "ServeHTTP" { + continue + } + + funcptr := method.Func.Pointer() + p1 := unsafe.Pointer(&funcptr) + p2 := unsafe.Pointer(&p1) + testfunc := (*func(*T, http.ResponseWriter, *http.Request))(p2) + methods[name+"."+method.Name] = func(w http.ResponseWriter, r *http.Request) { + (*testfunc)(receiver, w, r) + } + } + + return HttpApiReceiver{ + methods: methods, + } +} + +type HttpApiHandlerContainer struct { + methods map[string]apiFuncType +} + +func (hc *HttpApiHandlerContainer) RegistReceiver(receiver HttpApiReceiver) { + for k, v := range receiver.methods { + logger.Println("http api registered :", k) + hc.methods[k] = v + } +} + +func (hc *HttpApiHandlerContainer) HandlerFunc(serveMux *http.ServeMux, prefix string) { + for k, v := range hc.methods { + serveMux.HandleFunc(MakeHttpHandlerPattern(prefix, k), v) + } +}