gateway_rest/servlet/rest-servlet.go

166 lines
4.1 KiB
Go
Raw Normal View History

2018-04-06 12:00:01 +00:00
package servlet
import (
"fmt"
2018-04-10 13:17:46 +00:00
"reflect"
2018-04-06 12:00:01 +00:00
2018-04-10 13:17:46 +00:00
cdr "git.loafle.net/commons/di-go/registry"
crr "git.loafle.net/commons/rest-go/registry"
2018-04-06 12:00:01 +00:00
"git.loafle.net/commons/server-go"
csw "git.loafle.net/commons/server-go/web"
cswf "git.loafle.net/commons/server-go/web/fasthttp"
2018-04-10 13:17:46 +00:00
oca "git.loafle.net/overflow/commons-go/annotation"
2018-04-06 12:00:01 +00:00
"github.com/valyala/fasthttp"
)
type MethodMapping struct {
Method string
ParamKeys []string
}
type RESTServlet interface {
cswf.Servlet
2018-04-10 13:17:46 +00:00
RegisterRESTServices(services []interface{}) error
2018-04-06 12:00:01 +00:00
}
type RESTServlets struct {
cswf.Servlets
2018-04-10 13:19:20 +00:00
restRegistry crr.RESTRegistry
2018-04-06 12:00:01 +00:00
2018-04-10 13:19:20 +00:00
methodMapping map[string]map[string]*MethodMapping
2018-04-10 13:17:46 +00:00
}
func (s *RESTServlets) Init(serverCtx server.ServerCtx) error {
if err := s.Servlets.Init(serverCtx); nil != err {
return err
}
2018-04-10 13:19:20 +00:00
if nil == s.methodMapping {
s.methodMapping = make(map[string]map[string]*MethodMapping)
2018-04-10 13:17:46 +00:00
}
return nil
2018-04-06 12:00:01 +00:00
}
func (s *RESTServlets) Handle(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx) *csw.Error {
method := string(ctx.Method())
2018-04-10 13:17:46 +00:00
path := string(ctx.Path())
2018-04-10 14:08:55 +00:00
requestPath := s.RequestPath(ctx)
2018-04-10 13:19:20 +00:00
es, ok := s.methodMapping[method]
2018-04-10 13:17:46 +00:00
if !ok {
return csw.NewError(fasthttp.StatusNotFound, fmt.Errorf("Not Found for [%s]%s", method, path))
}
2018-04-10 14:08:55 +00:00
mapping, ok := es[requestPath]
2018-04-10 13:17:46 +00:00
if !ok {
return csw.NewError(fasthttp.StatusNotFound, fmt.Errorf("Not Found for [%s]%s", method, path))
}
2018-04-06 12:00:01 +00:00
switch method {
case "GET":
2018-04-10 13:17:46 +00:00
return s.HandleGet(servletCtx, ctx, mapping)
2018-04-06 12:00:01 +00:00
case "POST":
2018-04-10 13:17:46 +00:00
return s.HandlePost(servletCtx, ctx, mapping)
2018-04-06 12:00:01 +00:00
}
return nil
}
2018-04-10 13:17:46 +00:00
func (s *RESTServlets) HandleGet(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx, mapping *MethodMapping) *csw.Error {
2018-04-06 12:00:01 +00:00
params := make([]string, 0)
2018-04-10 13:17:46 +00:00
if nil != mapping.ParamKeys {
2018-04-06 12:00:01 +00:00
qargs := ctx.QueryArgs()
if nil == qargs {
return csw.NewError(fasthttp.StatusBadRequest, fmt.Errorf("Parameter is not valied"))
}
for _, k := range mapping.ParamKeys {
buf := qargs.Peek(k)
if nil == buf {
return csw.NewError(fasthttp.StatusBadRequest, fmt.Errorf("Parameter for %s is not valied", k))
}
params = append(params, string(buf))
}
}
2018-04-10 13:19:20 +00:00
_, err := s.restRegistry.Invoke(mapping.Method, params, servletCtx, ctx)
2018-04-10 13:17:46 +00:00
2018-04-06 12:00:01 +00:00
if nil != err {
2018-04-10 13:17:46 +00:00
return csw.NewError(fasthttp.StatusInternalServerError, err)
2018-04-06 12:00:01 +00:00
}
2018-04-10 13:17:46 +00:00
return nil
}
2018-04-06 12:00:01 +00:00
2018-04-10 13:17:46 +00:00
func (s *RESTServlets) HandlePost(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx, mapping *MethodMapping) *csw.Error {
params := make([]string, 0)
if nil != mapping.ParamKeys {
pargs := ctx.PostArgs()
if nil == pargs {
return csw.NewError(fasthttp.StatusBadRequest, fmt.Errorf("Parameter is not valied"))
}
for _, k := range mapping.ParamKeys {
buf := pargs.Peek(k)
if nil == buf {
return csw.NewError(fasthttp.StatusBadRequest, fmt.Errorf("Parameter for %s is not valied", k))
}
params = append(params, string(buf))
}
2018-04-10 06:21:42 +00:00
}
2018-04-10 13:19:20 +00:00
_, err := s.restRegistry.Invoke(mapping.Method, params, servletCtx, ctx)
2018-04-10 13:17:46 +00:00
2018-04-06 12:00:01 +00:00
if nil != err {
return csw.NewError(fasthttp.StatusInternalServerError, err)
}
return nil
}
2018-04-10 13:17:46 +00:00
func (s *RESTServlets) RegisterRESTServices(services []interface{}) error {
if nil == services || 0 == len(services) {
return nil
2018-04-06 12:00:01 +00:00
}
2018-04-10 13:19:20 +00:00
s.methodMapping = make(map[string]map[string]*MethodMapping)
s.restRegistry = crr.NewRESTRegistry()
2018-04-06 12:00:01 +00:00
2018-04-10 13:17:46 +00:00
LOOP:
for _, service := range services {
t := reflect.TypeOf(service)
ta := cdr.GetTypeAnnotation(t, oca.RESTServiceAnnotationType)
if nil == ta {
return fmt.Errorf("Service[%s] is not RESTService, use @RESTService", t.Elem().Name())
}
2018-04-10 13:19:20 +00:00
s.restRegistry.RegisterService(service, "")
2018-04-06 12:00:01 +00:00
2018-04-10 13:17:46 +00:00
mas := cdr.GetMethodAnnotations(t, oca.RequestMappingAnnotationType)
if nil == mas || 0 == len(mas) {
continue LOOP
}
2018-04-10 06:21:42 +00:00
2018-04-10 13:17:46 +00:00
for methodName, v := range mas {
ma := v.(*oca.RequestMappingAnnotation)
2018-04-10 13:19:20 +00:00
mm, ok := s.methodMapping[ma.Method]
2018-04-10 13:17:46 +00:00
if !ok {
mm = make(map[string]*MethodMapping)
2018-04-10 13:19:20 +00:00
s.methodMapping[ma.Method] = mm
2018-04-10 13:17:46 +00:00
}
2018-04-06 12:00:01 +00:00
2018-04-10 13:17:46 +00:00
_, ok = mm[ma.Entry]
if ok {
return fmt.Errorf("Mapping of method[%s], entry[%s] is exist already", ma.Method, ma.Entry)
}
2018-04-06 12:00:01 +00:00
2018-04-10 13:17:46 +00:00
mm[ma.Entry] = &MethodMapping{
Method: fmt.Sprintf("%s.%s", t.Elem().Name(), methodName),
ParamKeys: ma.Params,
}
}
}
2018-04-06 12:00:01 +00:00
return nil
}