1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2025-01-06 00:18:50 +02:00

[#2957] added support for wrapped api errors

This commit is contained in:
Gani Georgiev 2023-07-20 22:01:58 +03:00
parent ac52befb5b
commit 1e4c665b53
3 changed files with 100 additions and 10 deletions

View File

@ -91,6 +91,8 @@
- Added `?download` file query parameter option to instruct the browser to always download a file and not show a preview.
- Added support for wrapped API errors (_in case Go 1.20+ is used with multiple wrapped errors, `apis.ApiError` takes precedence_).
## v0.16.10

View File

@ -52,6 +52,10 @@ func InitApi(app core.App) (*echo.Echo, error) {
// custom error handler
e.HTTPErrorHandler = func(c echo.Context, err error) {
if err == nil {
return // no error
}
if c.Response().Committed {
if app.IsDebug() {
log.Println("HTTPErrorHandler response was already committed:", err)
@ -61,24 +65,22 @@ func InitApi(app core.App) (*echo.Echo, error) {
var apiErr *ApiError
switch v := err.(type) {
case *echo.HTTPError:
if errors.As(err, &apiErr) {
if app.IsDebug() && apiErr.RawData() != nil {
log.Println(apiErr.RawData())
}
} else if v := new(echo.HTTPError); errors.As(err, &v) {
if v.Internal != nil && app.IsDebug() {
log.Println(v.Internal)
}
msg := fmt.Sprintf("%v", v.Message)
apiErr = NewApiError(v.Code, msg, v)
case *ApiError:
if app.IsDebug() && v.RawData() != nil {
log.Println(v.RawData())
}
apiErr = v
default:
if err != nil && app.IsDebug() {
} else {
if app.IsDebug() {
log.Println(err)
}
if err != nil && errors.Is(err, sql.ErrNoRows) {
if errors.Is(err, sql.ErrNoRows) {
apiErr = NewNotFoundError("", err)
} else {
apiErr = NewBadRequestError("", err)

View File

@ -1,6 +1,7 @@
package apis_test
import (
"database/sql"
"errors"
"fmt"
"net/http"
@ -314,3 +315,88 @@ func TestEagerRequestInfoCache(t *testing.T) {
scenario.Test(t)
}
}
func TestErrorHandler(t *testing.T) {
scenarios := []tests.ApiScenario{
{
Name: "apis.ApiError",
Method: http.MethodGet,
Url: "/test",
BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
e.GET("/test", func(c echo.Context) error {
return apis.NewApiError(418, "test", nil)
})
},
ExpectedStatus: 418,
ExpectedContent: []string{`"message":"Test."`},
},
{
Name: "wrapped apis.ApiError",
Method: http.MethodGet,
Url: "/test",
BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
e.GET("/test", func(c echo.Context) error {
return fmt.Errorf("example 123: %w", apis.NewApiError(418, "test", nil))
})
},
ExpectedStatus: 418,
ExpectedContent: []string{`"message":"Test."`},
NotExpectedContent: []string{"example", "123"},
},
{
Name: "echo.HTTPError",
Method: http.MethodGet,
Url: "/test",
BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
e.GET("/test", func(c echo.Context) error {
return echo.NewHTTPError(418, "test")
})
},
ExpectedStatus: 418,
ExpectedContent: []string{`"message":"Test."`},
},
{
Name: "wrapped echo.HTTPError",
Method: http.MethodGet,
Url: "/test",
BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
e.GET("/test", func(c echo.Context) error {
return fmt.Errorf("example 123: %w", echo.NewHTTPError(418, "test"))
})
},
ExpectedStatus: 418,
ExpectedContent: []string{`"message":"Test."`},
NotExpectedContent: []string{"example", "123"},
},
{
Name: "wrapped sql.ErrNoRows",
Method: http.MethodGet,
Url: "/test",
BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
e.GET("/test", func(c echo.Context) error {
return fmt.Errorf("example 123: %w", sql.ErrNoRows)
})
},
ExpectedStatus: 404,
ExpectedContent: []string{`"data":{}`},
NotExpectedContent: []string{"example", "123"},
},
{
Name: "custom error",
Method: http.MethodGet,
Url: "/test",
BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
e.GET("/test", func(c echo.Context) error {
return fmt.Errorf("example 123")
})
},
ExpectedStatus: 400,
ExpectedContent: []string{`"data":{}`},
NotExpectedContent: []string{"example", "123"},
},
}
for _, scenario := range scenarios {
scenario.Test(t)
}
}