package servlet import ( "fmt" crp "git.loafle.net/commons/rpc-go/protocol" crr "git.loafle.net/commons/rpc-go/registry" "git.loafle.net/commons/server-go" csw "git.loafle.net/commons/server-go/web" cswf "git.loafle.net/commons/server-go/web/fasthttp" "github.com/valyala/fasthttp" ) type MethodMapping struct { Method string ParamKeys []string } type RESTServlet struct { cswf.Servlets ServerCodec crp.ServerCodec RPCInvoker crr.RPCInvoker MethodMapping map[string]MethodMapping } func (s *RESTServlet) Handle(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx) *csw.Error { method := string(ctx.Method()) switch method { case "GET": return s.HandleGet(servletCtx, ctx) case "POST": return s.HandlePost(servletCtx, ctx) } return nil } func (s *RESTServlet) HandleGet(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx) *csw.Error { path := string(ctx.Path()) if nil == s.MethodMapping { return csw.NewError(fasthttp.StatusNotFound, fmt.Errorf("Not Found for %s", path)) } mapping, ok := s.MethodMapping[path] if !ok { return csw.NewError(fasthttp.StatusNotFound, fmt.Errorf("Not Found for %s", path)) } method := mapping.Method params := make([]string, 0) if nil != mapping.ParamKeys && 0 < len(mapping.ParamKeys) { 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)) } } reqCodec, err := s.ServerCodec.NewRequestWithString(method, params, nil) if nil != err { return csw.NewError(fasthttp.StatusBadRequest, err) } reply, err := s.RPCInvoker.Invoke(reqCodec, servletCtx, ctx) buf, err := reqCodec.NewResponse(reply, err) if nil != err { return csw.NewError(fasthttp.StatusInternalServerError, err) } ctx.SetBody(buf) return nil } func (s *RESTServlet) HandlePost(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx) *csw.Error { buf := ctx.PostBody() if nil == buf { return csw.NewError(fasthttp.StatusBadRequest, fmt.Errorf("Parameter is not valied")) } reqCodec, err := s.ServerCodec.NewRequest(buf) if nil != err { return csw.NewError(fasthttp.StatusBadRequest, err) } reply, err := s.RPCInvoker.Invoke(reqCodec, servletCtx, ctx) buf, err = reqCodec.NewResponse(reply, err) if nil != err { return csw.NewError(fasthttp.StatusInternalServerError, err) } ctx.SetBody(buf) return nil }