mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-12-28 22:21:10 +02:00
* Refactored errors * Make monitoring and errorreport accept `errctx.Error` instead of `error` * Add server.Error; Remove category from errctx; Make HTTP handlers respond with *server.Error * Remove stackSkip from errctx.Wrap; Add errctx.WrapWithStackSkip
98 lines
2.8 KiB
Go
98 lines
2.8 KiB
Go
package errctx
|
|
|
|
// WrappedError is an implementation of [Error] that wraps another error.
|
|
//
|
|
// It also implements the Unwrap and Cause methods to retrieve the wrapped error.
|
|
//
|
|
// When implementing a custom error type that wraps another error,
|
|
// embed [WrappedError] to provide standard behavior.
|
|
type WrappedError struct {
|
|
error
|
|
*ErrorContext
|
|
}
|
|
|
|
// NewWrappedError creates a new [WrappedError] with the given error and options.
|
|
// It wraps the provided even if it already is an [WrappedError] and always
|
|
// creates a new context.
|
|
// To avoid double wrapping and reuse existing context, use [Wrap] instead.
|
|
func NewWrappedError(err error, stackSkip int, opts ...Option) *WrappedError {
|
|
return &WrappedError{
|
|
error: err,
|
|
ErrorContext: newErrorContext(stackSkip+1, opts...),
|
|
}
|
|
}
|
|
|
|
// Wrap creates a new [WrappedError] with the given error and options.
|
|
// It gets the stack trace from the call site.
|
|
//
|
|
// If the provided error already an [Error], it clones its context and applies
|
|
// the new options to it.
|
|
//
|
|
// If the provided error is already an [WrappedError], it rewraps its inner error
|
|
// to avoid double wrapping.
|
|
func Wrap(err error, opts ...Option) Error {
|
|
return WrapWithStackSkip(err, 1, opts...)
|
|
}
|
|
|
|
// WrapWithStackSkip creates a new [WrappedError] with the given error and options.
|
|
// It the first stackSkip frames from the call stack.
|
|
//
|
|
// If the provided error already an [Error], it clones its context and applies
|
|
// the new options to it.
|
|
//
|
|
// If the provided error is already an [WrappedError], it rewraps its inner error
|
|
// to avoid double wrapping.
|
|
func WrapWithStackSkip(err error, stackSkip int, opts ...Option) Error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
|
|
var ec *ErrorContext
|
|
|
|
// Check if the error already has context
|
|
if ewc, ok := err.(Error); ok {
|
|
// If the error already has context and no new options are provided,
|
|
// we don't need to wrap it again and can return it as is.
|
|
if len(opts) == 0 {
|
|
return ewc
|
|
}
|
|
|
|
// Clone the existing context to avoid modifying the original one
|
|
// and apply new options
|
|
ec = ewc.CloneErrorContext(opts...)
|
|
|
|
// If the error is already an WrappedError, get its inner error
|
|
// to avoid double wrapping
|
|
if ew, ok := err.(*WrappedError); ok {
|
|
err = ew.Unwrap()
|
|
}
|
|
} else {
|
|
// If the error does not have context, create a new one
|
|
ec = newErrorContext(stackSkip+1, opts...)
|
|
}
|
|
|
|
return &WrappedError{
|
|
error: err,
|
|
ErrorContext: ec,
|
|
}
|
|
}
|
|
|
|
// Error returns the error message with prefix if set.
|
|
func (e *WrappedError) Error() string {
|
|
if len(e.prefix) > 0 {
|
|
return e.prefix + ": " + e.error.Error()
|
|
}
|
|
return e.error.Error()
|
|
}
|
|
|
|
// Unwrap returns the wrapped error.
|
|
func (e *WrappedError) Unwrap() error {
|
|
return e.error
|
|
}
|
|
|
|
// Cause returns the wrapped error.
|
|
// This method is provided for compatibility with github.com/pkg/errors.
|
|
func (e *WrappedError) Cause() error {
|
|
return e.error
|
|
}
|