From 520901c3317b8d7350be2330e820a8aaf4519043 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 1 Aug 2025 23:53:30 +0300 Subject: [PATCH] update script error handling --- internal/server/gateway/route.go | 6 +++--- internal/server/rpc/responsers.go | 13 ++++++++++++- internal/server/sv1/handle.go | 6 +++--- internal/server/sv1/lua_handler.go | 23 ++++++++++++++++------- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/internal/server/gateway/route.go b/internal/server/gateway/route.go index ee2b22a..b526564 100644 --- a/internal/server/gateway/route.go +++ b/internal/server/gateway/route.go @@ -106,17 +106,17 @@ func (gs *GatewayServer) Handle(w http.ResponseWriter, r *http.Request) { func (gs *GatewayServer) Route(ctx context.Context, sid string, r *http.Request, req *rpc.RPCRequest) (resp *rpc.RPCResponse) { defer utils.CatchPanicWithFallback(func(rec any) { gs.x.SLog.Error("panic caught in handler", slog.Any("error", rec)) - resp = rpc.NewError(rpc.ErrInternalError, "Internal server error (panic)", req.ID) + resp = rpc.NewError(rpc.ErrInternalError, "Internal server error (panic)", nil, req.ID) }) if req.JSONRPC != rpc.JSONRPCVersion { gs.x.SLog.Info("invalid request received", slog.String("issue", rpc.ErrInvalidRequestS), slog.String("requested-version", req.JSONRPC)) - return rpc.NewError(rpc.ErrInvalidRequest, rpc.ErrInvalidRequestS, req.ID) + return rpc.NewError(rpc.ErrInvalidRequest, rpc.ErrInvalidRequestS, nil, req.ID) } server, ok := gs.servers[serversApiVer(req.ContextVersion)] if !ok { gs.x.SLog.Info("invalid request received", slog.String("issue", rpc.ErrContextVersionS), slog.String("requested-version", req.ContextVersion)) - return rpc.NewError(rpc.ErrContextVersion, rpc.ErrContextVersionS, req.ID) + return rpc.NewError(rpc.ErrContextVersion, rpc.ErrContextVersionS, nil, req.ID) } // checks if request is notification diff --git a/internal/server/rpc/responsers.go b/internal/server/rpc/responsers.go index 5f3a91d..e9a6b3f 100644 --- a/internal/server/rpc/responsers.go +++ b/internal/server/rpc/responsers.go @@ -2,7 +2,18 @@ package rpc import "encoding/json" -func NewError(code int, message string, id *json.RawMessage) *RPCResponse { +func NewError(code int, message string, data any, id *json.RawMessage) *RPCResponse { + if data != nil { + return &RPCResponse{ + JSONRPC: JSONRPCVersion, + ID: id, + Error: map[string]any{ + "code": code, + "message": message, + "data": data, + }, + } + } return &RPCResponse{ JSONRPC: JSONRPCVersion, ID: id, diff --git a/internal/server/sv1/handle.go b/internal/server/sv1/handle.go index 84abc10..a81d284 100644 --- a/internal/server/sv1/handle.go +++ b/internal/server/sv1/handle.go @@ -11,17 +11,17 @@ import ( func (h *HandlerV1) Handle(_ context.Context, sid string, r *http.Request, req *rpc.RPCRequest) *rpc.RPCResponse { if req.Method == "" { h.x.SLog.Info("invalid request received", slog.String("issue", rpc.ErrMethodNotFoundS), slog.String("requested-method", req.Method)) - return rpc.NewError(rpc.ErrMethodIsMissing, rpc.ErrMethodIsMissingS, req.ID) + return rpc.NewError(rpc.ErrMethodIsMissing, rpc.ErrMethodIsMissingS, nil, req.ID) } method, err := h.resolveMethodPath(req.Method) if err != nil { if err.Error() == rpc.ErrInvalidMethodFormatS { h.x.SLog.Info("invalid request received", slog.String("issue", rpc.ErrInvalidMethodFormatS), slog.String("requested-method", req.Method)) - return rpc.NewError(rpc.ErrInvalidMethodFormat, rpc.ErrInvalidMethodFormatS, req.ID) + return rpc.NewError(rpc.ErrInvalidMethodFormat, rpc.ErrInvalidMethodFormatS, nil, req.ID) } else if err.Error() == rpc.ErrMethodNotFoundS { h.x.SLog.Info("invalid request received", slog.String("issue", rpc.ErrMethodNotFoundS), slog.String("requested-method", req.Method)) - return rpc.NewError(rpc.ErrMethodNotFound, rpc.ErrMethodNotFoundS, req.ID) + return rpc.NewError(rpc.ErrMethodNotFound, rpc.ErrMethodNotFoundS, nil, req.ID) } } diff --git a/internal/server/sv1/lua_handler.go b/internal/server/sv1/lua_handler.go index 0ef7a8f..e21da1b 100644 --- a/internal/server/sv1/lua_handler.go +++ b/internal/server/sv1/lua_handler.go @@ -247,26 +247,26 @@ func (h *HandlerV1) handleLUA(sid string, r *http.Request, req *rpc.RPCRequest, if _, err := os.Stat(prep); err == nil { if err := L.DoFile(prep); err != nil { h.x.SLog.Error("script error", slog.String("script", path), slog.String("error", err.Error())) - return rpc.NewError(rpc.ErrInternalError, rpc.ErrInternalErrorS, req.ID) + return rpc.NewError(rpc.ErrInternalError, rpc.ErrInternalErrorS, nil, req.ID) } } if err := L.DoFile(path); err != nil { h.x.SLog.Error("script error", slog.String("script", path), slog.String("error", err.Error())) - return rpc.NewError(rpc.ErrInternalError, rpc.ErrInternalErrorS, req.ID) + return rpc.NewError(rpc.ErrInternalError, rpc.ErrInternalErrorS, nil, req.ID) } pkg := L.GetGlobal("package") pkgTbl, ok := pkg.(*lua.LTable) if !ok { h.x.SLog.Error("script error", slog.String("script", path), slog.String("error", "package not found")) - return rpc.NewError(rpc.ErrInternalError, rpc.ErrInternalErrorS, req.ID) + return rpc.NewError(rpc.ErrInternalError, rpc.ErrInternalErrorS, nil, req.ID) } loaded := pkgTbl.RawGetString("loaded") loadedTbl, ok := loaded.(*lua.LTable) if !ok { h.x.SLog.Error("script error", slog.String("script", path), slog.String("error", "package.loaded not found")) - return rpc.NewError(rpc.ErrInternalError, rpc.ErrInternalErrorS, req.ID) + return rpc.NewError(rpc.ErrInternalError, rpc.ErrInternalErrorS, nil, req.ID) } sessionVal := loadedTbl.RawGetString("session") @@ -288,23 +288,32 @@ func (h *HandlerV1) handleLUA(sid string, r *http.Request, req *rpc.RPCRequest, outTbl, ok := outVal.(*lua.LTable) if !ok { h.x.SLog.Error("script error", slog.String("script", path), slog.String("error", "response is not a table")) - return rpc.NewError(rpc.ErrInternalError, rpc.ErrInternalErrorS, req.ID) + return rpc.NewError(rpc.ErrInternalError, rpc.ErrInternalErrorS, nil, req.ID) } if errVal := outTbl.RawGetString("error"); errVal != lua.LNil { if errTbl, ok := errVal.(*lua.LTable); ok { code := rpc.ErrInternalError message := rpc.ErrInternalErrorS + data := make(map[string]any) if c := errTbl.RawGetString("code"); c.Type() == lua.LTNumber { code = int(c.(lua.LNumber)) } if msg := errTbl.RawGetString("message"); msg.Type() == lua.LTString { message = msg.String() } + rawData := errTbl.RawGetString("data") + + if tbl, ok := rawData.(*lua.LTable); ok { + tbl.ForEach(func(k, v lua.LValue) {data[k.String()] = ConvertLuaTypesToGolang(v)}) + } else { + h.x.SLog.Error("the script terminated with an error", slog.String("code", strconv.Itoa(code)), slog.String("message", message)) + return rpc.NewError(code, message, rawData, req.ID) + } h.x.SLog.Error("the script terminated with an error", slog.String("code", strconv.Itoa(code)), slog.String("message", message)) - return rpc.NewError(code, message, req.ID) + return rpc.NewError(code, message, data, req.ID) } - return rpc.NewError(rpc.ErrInternalError, rpc.ErrInternalErrorS, req.ID) + return rpc.NewError(rpc.ErrInternalError, rpc.ErrInternalErrorS, nil, req.ID) } resultVal := outTbl.RawGetString("result")