Compare commits

...

6 Commits

Author SHA1 Message Date
7fe3e66cad v0.0.196 2023-07-24 11:47:47 +02:00
a73d7d1654 v0.0.195 2023-07-24 11:42:52 +02:00
bbd7a7bc2c v0.0.194 2023-07-24 11:40:47 +02:00
f5151eb214 v0.0.193 2023-07-24 11:38:57 +02:00
eefb9ac9f5 v0.0.192 2023-07-24 11:30:07 +02:00
468a7d212d v0.0.191 2023-07-24 11:18:25 +02:00
7 changed files with 86 additions and 45 deletions

View File

@@ -13,6 +13,7 @@ var (
CatForeign = ErrorCategory{"Foreign"} // A foreign error that some component threw (e.g. an unknown mongodb error), happens if we call Wrap(..) on an non-bmerror value CatForeign = ErrorCategory{"Foreign"} // A foreign error that some component threw (e.g. an unknown mongodb error), happens if we call Wrap(..) on an non-bmerror value
) )
//goland:noinspection GoUnusedGlobalVariable
var AllCategories = []ErrorCategory{CatWrap, CatSystem, CatUser, CatForeign} var AllCategories = []ErrorCategory{CatWrap, CatSystem, CatUser, CatForeign}
type ErrorSeverity struct{ Severity string } type ErrorSeverity struct{ Severity string }
@@ -26,6 +27,7 @@ var (
SevFatal = ErrorSeverity{"Fatal"} SevFatal = ErrorSeverity{"Fatal"}
) )
//goland:noinspection GoUnusedGlobalVariable
var AllSeverities = []ErrorSeverity{SevTrace, SevDebug, SevInfo, SevWarn, SevErr, SevFatal} var AllSeverities = []ErrorSeverity{SevTrace, SevDebug, SevInfo, SevWarn, SevErr, SevFatal}
type ErrorType struct { type ErrorType struct {
@@ -33,6 +35,7 @@ type ErrorType struct {
DefaultStatusCode *int DefaultStatusCode *int
} }
//goland:noinspection GoUnusedGlobalVariable
var ( var (
TypeInternal = ErrorType{"INTERNAL_ERROR", langext.Ptr(500)} TypeInternal = ErrorType{"INTERNAL_ERROR", langext.Ptr(500)}
TypePanic = ErrorType{"PANIC", langext.Ptr(500)} TypePanic = ErrorType{"PANIC", langext.Ptr(500)}
@@ -51,7 +54,7 @@ var (
// other values come from pkgconfig // other values come from pkgconfig
) )
func NewType(key string, defStatusCode *int) { func NewType(key string, defStatusCode *int) ErrorType {
return ErrorType{key, defStatusCode} return ErrorType{key, defStatusCode}
} }

View File

@@ -10,8 +10,8 @@ type ErrorPackageConfig struct {
ZeroLogAllTraces bool // autom print zerolog logs on .Build() (for all Severities) ZeroLogAllTraces bool // autom print zerolog logs on .Build() (for all Severities)
RecursiveErrors bool // errors contains their Origin-Error RecursiveErrors bool // errors contains their Origin-Error
ExtendedGinOutput bool // Log extended data (trace, meta, ...) to gin in err.Output() ExtendedGinOutput bool // Log extended data (trace, meta, ...) to gin in err.Output()
ExtendGinOutput func(json map[string]any) // (Optionally) extend the gin output with more fields ExtendGinOutput func(err *ExErr, json map[string]any) // (Optionally) extend the gin output with more fields
ExtendGinDataOutput func(json map[string]any) // (Optionally) extend the gin `__data` output with more fields ExtendGinDataOutput func(err *ExErr, depth int, json map[string]any) // (Optionally) extend the gin `__data` output with more fields
} }
type ErrorPackageConfigInit struct { type ErrorPackageConfigInit struct {
@@ -19,8 +19,8 @@ type ErrorPackageConfigInit struct {
ZeroLogAllTraces bool ZeroLogAllTraces bool
RecursiveErrors bool RecursiveErrors bool
ExtendedGinOutput bool ExtendedGinOutput bool
ExtendGinOutput *func(json map[string]any) ExtendGinOutput func(err *ExErr, json map[string]any)
ExtendGinDataOutput *func(json map[string]any) ExtendGinDataOutput func(err *ExErr, depth int, json map[string]any)
} }
var initialized = false var initialized = false
@@ -30,8 +30,8 @@ var pkgconfig = ErrorPackageConfig{
ZeroLogAllTraces: false, ZeroLogAllTraces: false,
RecursiveErrors: true, RecursiveErrors: true,
ExtendedGinOutput: false, ExtendedGinOutput: false,
ExtendGinOutput: func(json map[string]any) {}, ExtendGinOutput: func(err *ExErr, json map[string]any) {},
ExtendGinDataOutput: func(json map[string]any) {}, ExtendGinDataOutput: func(err *ExErr, depth int, json map[string]any) {},
} }
// Init initializes the exerr packages // Init initializes the exerr packages
@@ -42,13 +42,23 @@ func Init(cfg ErrorPackageConfigInit) {
panic("Cannot re-init error package") panic("Cannot re-init error package")
} }
ego := func(err *ExErr, json map[string]any) {}
egdo := func(err *ExErr, depth int, json map[string]any) {}
if cfg.ExtendGinOutput != nil {
ego = cfg.ExtendGinOutput
}
if cfg.ExtendGinDataOutput != nil {
egdo = cfg.ExtendGinDataOutput
}
pkgconfig = ErrorPackageConfig{ pkgconfig = ErrorPackageConfig{
ZeroLogErrTraces: cfg.ZeroLogErrTraces, ZeroLogErrTraces: cfg.ZeroLogErrTraces,
ZeroLogAllTraces: cfg.ZeroLogAllTraces, ZeroLogAllTraces: cfg.ZeroLogAllTraces,
RecursiveErrors: cfg.RecursiveErrors, RecursiveErrors: cfg.RecursiveErrors,
ExtendedGinOutput: cfg.ExtendedGinOutput, ExtendedGinOutput: cfg.ExtendedGinOutput,
ExtendGinOutput: langext.Coalesce(cfg.ExtendGinOutput, func(json map[string]any) {}), ExtendGinOutput: ego,
ExtendGinDataOutput: langext.Coalesce(cfg.ExtendGinDataOutput, func(json map[string]any) {}), ExtendGinDataOutput: egdo,
} }
initialized = true initialized = true

View File

@@ -162,7 +162,6 @@ func (ee *ExErr) RecursiveStatuscode() *int {
} }
} }
// fallback to <empty>
return nil return nil
} }
@@ -179,6 +178,18 @@ func (ee *ExErr) RecursiveCategory() ErrorCategory {
return ee.Category return ee.Category
} }
// RecursiveMeta searches (top-down) for teh first error that has a meta value with teh specified key
// and returns its value (or nil)
func (ee *ExErr) RecursiveMeta(key string) *MetaValue {
for curr := ee; curr != nil; curr = curr.OriginalError {
if metaval, ok := curr.Meta[key]; ok {
return langext.Ptr(metaval)
}
}
return nil
}
func (ee *ExErr) Depth() int { func (ee *ExErr) Depth() int {
if ee.OriginalError == nil { if ee.OriginalError == nil {
return 1 return 1

View File

@@ -7,43 +7,43 @@ import (
"time" "time"
) )
func (ee *ExErr) toJson() gin.H { func (ee *ExErr) toJson(depth int) gin.H {
json := gin.H{} ginJson := gin.H{}
if ee.UniqueID != "" { if ee.UniqueID != "" {
json["id"] = ee.UniqueID ginJson["id"] = ee.UniqueID
} }
if ee.Category != CatWrap { if ee.Category != CatWrap {
json["category"] = ee.Category ginJson["category"] = ee.Category
} }
if ee.Type != TypeWrap { if ee.Type != TypeWrap {
json["type"] = ee.Type ginJson["type"] = ee.Type
} }
if ee.StatusCode != nil { if ee.StatusCode != nil {
json["statuscode"] = ee.StatusCode ginJson["statuscode"] = ee.StatusCode
} }
if ee.Message != "" { if ee.Message != "" {
json["message"] = ee.Message ginJson["message"] = ee.Message
} }
if ee.Caller != "" { if ee.Caller != "" {
json["caller"] = ee.Caller ginJson["caller"] = ee.Caller
} }
if ee.Severity != SevErr { if ee.Severity != SevErr {
json["severity"] = ee.Severity ginJson["severity"] = ee.Severity
} }
if ee.Timestamp != (time.Time{}) { if ee.Timestamp != (time.Time{}) {
json["time"] = ee.Timestamp.Format(time.RFC3339) ginJson["time"] = ee.Timestamp.Format(time.RFC3339)
} }
if ee.WrappedErrType != "" { if ee.WrappedErrType != "" {
json["wrappedErrType"] = ee.WrappedErrType ginJson["wrappedErrType"] = ee.WrappedErrType
} }
if ee.OriginalError != nil { if ee.OriginalError != nil {
json["original"] = ee.OriginalError.toJson() ginJson["original"] = ee.OriginalError.toJson(depth + 1)
} }
pkgconfig.ExtendGinDataOutput(json) pkgconfig.ExtendGinDataOutput(ee, depth, ginJson)
return json return ginJson
} }
func (ee *ExErr) Output(g *gin.Context) { func (ee *ExErr) Output(g *gin.Context) {
@@ -75,10 +75,10 @@ func (ee *ExErr) Output(g *gin.Context) {
} }
if pkgconfig.ExtendedGinOutput { if pkgconfig.ExtendedGinOutput {
ginOutput["__data"] = ee.toJson() ginOutput["__data"] = ee.toJson(0)
} }
pkgconfig.ExtendGinOutput(ginOutput) pkgconfig.ExtendGinOutput(ee, ginOutput)
g.Render(statuscode, json.GoJsonRender{Data: ginOutput, NilSafeSlices: true, NilSafeMaps: true}) g.Render(statuscode, json.GoJsonRender{Data: ginOutput, NilSafeSlices: true, NilSafeMaps: true})
} }

View File

@@ -50,10 +50,3 @@ func (ac *AppContext) RequestURI() string {
return "" return ""
} }
} }
func (ac *AppContext) FinishSuccess(res HTTPResponse) HTTPResponse {
if ac.cancelled {
panic("Cannot finish a cancelled request")
}
return res
}

View File

@@ -2,8 +2,10 @@ package ginext
import ( import (
"context" "context"
"fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding" "github.com/gin-gonic/gin/binding"
"gogs.mikescher.com/BlackForestBytes/goext/exerr"
"gogs.mikescher.com/BlackForestBytes/goext/langext" "gogs.mikescher.com/BlackForestBytes/goext/langext"
"runtime/debug" "runtime/debug"
) )
@@ -40,33 +42,55 @@ func (pctx *PreContext) Form(form any) *PreContext {
func (pctx PreContext) Start() (*AppContext, *gin.Context, *HTTPResponse) { func (pctx PreContext) Start() (*AppContext, *gin.Context, *HTTPResponse) {
if pctx.uri != nil { if pctx.uri != nil {
if err := pctx.ginCtx.ShouldBindUri(pctx.uri); err != nil { if err := pctx.ginCtx.ShouldBindUri(pctx.uri); err != nil {
return nil, nil, langext.Ptr(APIError(pctx.ginCtx, commonApiErr.BindFailURI, "Failed to read uri", err)) err = exerr.Wrap(err, "Failed to read uri").
WithType(exerr.TypeBindFailURI).
Str("struct_type", fmt.Sprintf("%T", pctx.uri)).
Build()
return nil, nil, langext.Ptr(APIError(pctx.ginCtx, err))
} }
} }
if pctx.query != nil { if pctx.query != nil {
if err := pctx.ginCtx.ShouldBindQuery(pctx.query); err != nil { if err := pctx.ginCtx.ShouldBindQuery(pctx.query); err != nil {
return nil, nil, langext.Ptr(APIError(pctx.ginCtx, commonApiErr.BindFailQuery, "Failed to read query", err)) err = exerr.Wrap(err, "Failed to read query").
WithType(exerr.TypeBindFailQuery).
Str("struct_type", fmt.Sprintf("%T", pctx.query)).
Build()
return nil, nil, langext.Ptr(APIError(pctx.ginCtx, err))
} }
} }
if pctx.body != nil { if pctx.body != nil {
if pctx.ginCtx.ContentType() == "application/json" { if pctx.ginCtx.ContentType() == "application/json" {
if err := pctx.ginCtx.ShouldBindJSON(pctx.body); err != nil { if err := pctx.ginCtx.ShouldBindJSON(pctx.body); err != nil {
return nil, nil, langext.Ptr(APIError(pctx.ginCtx, commonApiErr.BindFailJSON, "Failed to read body", err)) err = exerr.Wrap(err, "Failed to read json-body").
WithType(exerr.TypeBindFailJSON).
Str("struct_type", fmt.Sprintf("%T", pctx.body)).
Build()
return nil, nil, langext.Ptr(APIError(pctx.ginCtx, err))
} }
} else { } else {
return nil, nil, langext.Ptr(APIError(pctx.ginCtx, commonApiErr.BindFailJSON, "missing JSON body", nil)) err := exerr.New(exerr.TypeBindFailJSON, "missing JSON body").
Str("struct_type", fmt.Sprintf("%T", pctx.body)).
Build()
return nil, nil, langext.Ptr(APIError(pctx.ginCtx, err))
} }
} }
if pctx.form != nil { if pctx.form != nil {
if pctx.ginCtx.ContentType() == "multipart/form-data" { if pctx.ginCtx.ContentType() == "multipart/form-data" {
if err := pctx.ginCtx.ShouldBindWith(pctx.form, binding.Form); err != nil { if err := pctx.ginCtx.ShouldBindWith(pctx.form, binding.Form); err != nil {
return nil, nil, langext.Ptr(APIError(pctx.ginCtx, commonApiErr.BindFailFormData, "Failed to read multipart-form", err)) err = exerr.Wrap(err, "Failed to read multipart-form").
WithType(exerr.TypeBindFailFormData).
Str("struct_type", fmt.Sprintf("%T", pctx.form)).
Build()
return nil, nil, langext.Ptr(APIError(pctx.ginCtx, err))
} }
} else { } else {
return nil, nil, langext.Ptr(APIError(pctx.ginCtx, commonApiErr.BindFailJSON, "missing form body", nil)) err := exerr.New(exerr.TypeBindFailFormData, "missing form body").
Str("struct_type", fmt.Sprintf("%T", pctx.form)).
Build()
return nil, nil, langext.Ptr(APIError(pctx.ginCtx, err))
} }
} }

View File

@@ -1,5 +1,5 @@
package goext package goext
const GoextVersion = "0.0.190" const GoextVersion = "0.0.196"
const GoextVersionTimestamp = "2023-07-24T11:16:57+0200" const GoextVersionTimestamp = "2023-07-24T11:47:47+0200"