diff --git a/CHANGELOG.md b/CHANGELOG.md index 58098f874c4a1331731dfcbceb26984d4e52e603..fec56804d44dcc176793ed1956717db76e20c996 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ The format is based on [keep a changelog](http://keepachangelog.com/) and this p - Increase default maximum length of various name, location, timezone, and other free text fields to 255 characters. - Increase default maximum length of storage bucket, collection, and record from 70 to 128 characters. - Increase default maximum length of topic room names from 64 to 128 characters. +- Better error responses when runtime function RPC or HTTP hooks fail or return errors. ### Fixed - Realtime notification routing now correctly resolves connected users. diff --git a/server/pipeline_runtime.go b/server/pipeline_runtime.go index c8ad438ed895da46ff06ea25464624a81712d111..ca58f4a56f16dc27e15acd5dc2c1b481c1cf4313 100644 --- a/server/pipeline_runtime.go +++ b/server/pipeline_runtime.go @@ -15,9 +15,9 @@ package server import ( - "fmt" - + "github.com/yuin/gopher-lua" "go.uber.org/zap" + "strings" ) func (p *pipeline) rpc(logger *zap.Logger, session *session, envelope *Envelope) { @@ -36,7 +36,21 @@ func (p *pipeline) rpc(logger *zap.Logger, session *session, envelope *Envelope) result, fnErr := p.runtime.InvokeFunctionRPC(lf, session.userID, session.handle.Load(), session.expiry, rpcMessage.Payload) if fnErr != nil { logger.Error("Runtime RPC function caused an error", zap.String("id", rpcMessage.Id), zap.Error(fnErr)) - session.Send(ErrorMessage(envelope.CollationId, RUNTIME_FUNCTION_EXCEPTION, fmt.Sprintf("Runtime function caused an error: %s", fnErr.Error()))) + if apiErr, ok := fnErr.(*lua.ApiError); ok { + msg := apiErr.Object.String() + if strings.HasPrefix(msg, lf.Proto.SourceName) { + msg = msg[len(lf.Proto.SourceName):] + msgParts := strings.SplitN(msg, ": ", 2) + if len(msgParts) == 2 { + msg = msgParts[1] + } else { + msg = msgParts[0] + } + } + session.Send(ErrorMessage(envelope.CollationId, RUNTIME_FUNCTION_EXCEPTION, msg)) + } else { + session.Send(ErrorMessage(envelope.CollationId, RUNTIME_FUNCTION_EXCEPTION, fnErr.Error())) + } return } diff --git a/server/session_auth.go b/server/session_auth.go index 213f5f5c8001e9c1995a3c4b35ab184c3a240e60..f65bb58056efdbf3408d141bc5151a1d70970ab1 100644 --- a/server/session_auth.go +++ b/server/session_auth.go @@ -38,6 +38,7 @@ import ( "github.com/gorilla/mux" "github.com/gorilla/websocket" "github.com/satori/go.uuid" + "github.com/yuin/gopher-lua" "go.uber.org/zap" "golang.org/x/crypto/bcrypt" "nakama/pkg/httputil" @@ -230,7 +231,21 @@ func (a *authenticationService) configure() { responseData, funError := a.runtime.InvokeFunctionHTTP(fn, uuid.Nil, "", 0, payload) if funError != nil { a.logger.Error("Runtime function caused an error", zap.String("path", path), zap.Error(funError)) - http.Error(w, fmt.Sprintf("Runtime function caused an error: %s", funError.Error()), 500) + if apiErr, ok := funError.(*lua.ApiError); ok { + msg := apiErr.Object.String() + if strings.HasPrefix(msg, fn.Proto.SourceName) { + msg = msg[len(fn.Proto.SourceName):] + msgParts := strings.SplitN(msg, ": ", 2) + if len(msgParts) == 2 { + msg = msgParts[1] + } else { + msg = msgParts[0] + } + } + http.Error(w, msg, 500) + } else { + http.Error(w, funError.Error(), 500) + } return }