go-utils/common/server/server.go

68 lines
1.6 KiB
Go

package server
import (
"fmt"
"log"
"net/http"
"reflect"
"strings"
"sync"
)
type Server struct {
name string
val reflect.Value
typ reflect.Type
methods []reflect.Method
lock sync.Mutex
}
func NewServer() *Server {
server := new(Server)
server.methods = make([]reflect.Method, 0)
return server
}
func (s *Server) Start(addr string) error {
log.Println(fmt.Sprintf("server start on addr [%s]", addr))
return http.ListenAndServe(addr, s)
}
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for _, method := range s.methods {
if strings.ToLower("/"+s.name+"/"+method.Name) == r.URL.Path {
method.Func.Call([]reflect.Value{s.val, reflect.ValueOf(w), reflect.ValueOf(r)})
}
}
}
func (s *Server) Register(service interface{}) error {
s.lock.Lock()
defer s.lock.Unlock()
s.typ = reflect.TypeOf(service)
s.val = reflect.ValueOf(service)
s.name = reflect.Indirect(s.val).Type().Name()
if s.name == "" {
return fmt.Errorf("no service name for type %s", s.typ.String())
}
for m := 0; m < s.typ.NumMethod(); m++ {
method := s.typ.Method(m)
mtype := method.Type
if mtype.NumIn() != 3 {
return fmt.Errorf("method %s has wrong number of ins: %d", method.Name, mtype.NumIn())
}
reply := mtype.In(1)
if reply.String() != "http.ResponseWriter" {
return fmt.Errorf("%s argument type not exported: %s", method.Name, reply)
}
arg := mtype.In(2)
if arg.String() != "*http.Request" {
return fmt.Errorf("%s argument type not exported: %s", method.Name, arg)
}
s.methods = append(s.methods, method)
log.Println("registry path:", strings.ToLower("/"+s.name+"/"+method.Name))
}
return nil
}