updated jsvm errors handling
This commit is contained in:
parent
0110869c89
commit
71a70bac9d
15
apis/base.go
15
apis/base.go
|
@ -2,6 +2,7 @@
|
||||||
package apis
|
package apis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
@ -11,7 +12,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/dop251/goja"
|
|
||||||
"github.com/labstack/echo/v5"
|
"github.com/labstack/echo/v5"
|
||||||
"github.com/labstack/echo/v5/middleware"
|
"github.com/labstack/echo/v5/middleware"
|
||||||
"github.com/pocketbase/pocketbase/core"
|
"github.com/pocketbase/pocketbase/core"
|
||||||
|
@ -59,14 +59,6 @@ func InitApi(app core.App) (*echo.Echo, error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// manually extract the goja exception error value for
|
|
||||||
// consistency when throwing or returning errors
|
|
||||||
if jsException, ok := err.(*goja.Exception); ok {
|
|
||||||
if wrapped, ok := jsException.Value().Export().(error); ok {
|
|
||||||
err = wrapped
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var apiErr *ApiError
|
var apiErr *ApiError
|
||||||
|
|
||||||
switch v := err.(type) {
|
switch v := err.(type) {
|
||||||
|
@ -85,8 +77,13 @@ func InitApi(app core.App) (*echo.Echo, error) {
|
||||||
if err != nil && app.IsDebug() {
|
if err != nil && app.IsDebug() {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil && errors.Is(err, sql.ErrNoRows) {
|
||||||
|
apiErr = NewNotFoundError("", err)
|
||||||
|
} else {
|
||||||
apiErr = NewBadRequestError("", err)
|
apiErr = NewBadRequestError("", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
event := new(core.ApiErrorEvent)
|
event := new(core.ApiErrorEvent)
|
||||||
event.HttpContext = c
|
event.HttpContext = c
|
||||||
|
|
|
@ -214,7 +214,6 @@ func TestRemoveTrailingSlashMiddleware(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEagerRequestInfoCache(t *testing.T) {
|
func TestEagerRequestInfoCache(t *testing.T) {
|
||||||
|
|
||||||
scenarios := []tests.ApiScenario{
|
scenarios := []tests.ApiScenario{
|
||||||
{
|
{
|
||||||
Name: "custom non-api group route",
|
Name: "custom non-api group route",
|
||||||
|
|
|
@ -77,9 +77,7 @@ func hooksBinds(app core.App, loader *goja.Runtime, executors *vmsPool) {
|
||||||
|
|
||||||
// check for returned error or false
|
// check for returned error or false
|
||||||
if res != nil {
|
if res != nil {
|
||||||
exported := res.Export()
|
switch v := res.Export().(type) {
|
||||||
if exported != nil {
|
|
||||||
switch v := exported.(type) {
|
|
||||||
case error:
|
case error:
|
||||||
return v
|
return v
|
||||||
case bool:
|
case bool:
|
||||||
|
@ -88,7 +86,6 @@ func hooksBinds(app core.App, loader *goja.Runtime, executors *vmsPool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
@ -156,8 +153,16 @@ func routerBinds(app core.App, loader *goja.Runtime, executors *vmsPool) {
|
||||||
e.Router.Add(strings.ToUpper(method), path, func(c echo.Context) error {
|
e.Router.Add(strings.ToUpper(method), path, func(c echo.Context) error {
|
||||||
return executors.run(func(executor *goja.Runtime) error {
|
return executors.run(func(executor *goja.Runtime) error {
|
||||||
executor.Set("__args", []any{c})
|
executor.Set("__args", []any{c})
|
||||||
_, err := executor.RunProgram(pr)
|
res, err := executor.RunProgram(pr)
|
||||||
executor.Set("__args", goja.Undefined())
|
executor.Set("__args", goja.Undefined())
|
||||||
|
|
||||||
|
// check for returned error
|
||||||
|
if res != nil {
|
||||||
|
if v, ok := res.Export().(error); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}, wrappedMiddlewares...)
|
}, wrappedMiddlewares...)
|
||||||
|
@ -207,9 +212,17 @@ func wrapMiddlewares(executors *vmsPool, rawMiddlewares ...goja.Value) ([]echo.M
|
||||||
return executors.run(func(executor *goja.Runtime) error {
|
return executors.run(func(executor *goja.Runtime) error {
|
||||||
executor.Set("__args", []any{next})
|
executor.Set("__args", []any{next})
|
||||||
executor.Set("__args2", []any{c})
|
executor.Set("__args2", []any{c})
|
||||||
_, err := executor.RunProgram(pr)
|
res, err := executor.RunProgram(pr)
|
||||||
executor.Set("__args", goja.Undefined())
|
executor.Set("__args", goja.Undefined())
|
||||||
executor.Set("__args2", goja.Undefined())
|
executor.Set("__args2", goja.Undefined())
|
||||||
|
|
||||||
|
// check for returned error
|
||||||
|
if res != nil {
|
||||||
|
if v, ok := res.Export().(error); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/dop251/goja_nodejs/require"
|
"github.com/dop251/goja_nodejs/require"
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
|
"github.com/labstack/echo/v5"
|
||||||
"github.com/pocketbase/dbx"
|
"github.com/pocketbase/dbx"
|
||||||
"github.com/pocketbase/pocketbase/core"
|
"github.com/pocketbase/pocketbase/core"
|
||||||
m "github.com/pocketbase/pocketbase/migrations"
|
m "github.com/pocketbase/pocketbase/migrations"
|
||||||
|
@ -191,6 +192,11 @@ func (p *plugin) registerHooks() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
||||||
|
e.Router.HTTPErrorHandler = p.normalizeServeExceptions(e.Router.HTTPErrorHandler)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
// this is safe to be shared across multiple vms
|
// this is safe to be shared across multiple vms
|
||||||
registry := new(require.Registry)
|
registry := new(require.Registry)
|
||||||
|
|
||||||
|
@ -236,6 +242,34 @@ func (p *plugin) registerHooks() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// normalizeExceptions wraps the provided error handler and returns a new one
|
||||||
|
// with extracted goja exception error value for consistency when throwing or returning errors.
|
||||||
|
func (p *plugin) normalizeServeExceptions(oldErrorHandler echo.HTTPErrorHandler) echo.HTTPErrorHandler {
|
||||||
|
return func(c echo.Context, err error) {
|
||||||
|
defer func() {
|
||||||
|
oldErrorHandler(c, err)
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err == nil || c.Response().Committed {
|
||||||
|
return // no error or already committed
|
||||||
|
}
|
||||||
|
|
||||||
|
jsException, ok := err.(*goja.Exception)
|
||||||
|
if !ok {
|
||||||
|
return // no exception
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v := jsException.Value().Export().(type) {
|
||||||
|
case error:
|
||||||
|
err = v
|
||||||
|
case map[string]any: // goja.GoError
|
||||||
|
if vErr, ok := v["value"].(error); ok {
|
||||||
|
err = vErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// watchHooks initializes a hooks file watcher that will restart the
|
// watchHooks initializes a hooks file watcher that will restart the
|
||||||
// application (*if possible) in case of a change in the hooks directory.
|
// application (*if possible) in case of a change in the hooks directory.
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue