1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-12-23 22:11:10 +02:00
Files
imgproxy/ierrors/errors.go

168 lines
2.6 KiB
Go
Raw Permalink Normal View History

2021-04-26 17:52:50 +06:00
package ierrors
2017-10-05 01:44:58 +06:00
import (
"fmt"
"net/http"
2017-10-05 01:44:58 +06:00
"runtime"
"strings"
)
const (
defaultCategory = "default"
)
type Option func(*Error)
2021-04-26 17:52:50 +06:00
type Error struct {
err error
prefix string
statusCode int
publicMessage string
shouldReport bool
category string
2019-08-19 18:05:34 +06:00
stack []uintptr
2017-10-05 01:44:58 +06:00
}
2021-04-26 17:52:50 +06:00
func (e *Error) Error() string {
if len(e.prefix) > 0 {
return fmt.Sprintf("%s: %s", e.prefix, e.err.Error())
}
return e.err.Error()
2017-10-05 01:44:58 +06:00
}
func (e *Error) Unwrap() error {
return e.err
}
func (e *Error) Cause() error {
return e.err
}
func (e *Error) StatusCode() int {
if e.statusCode <= 0 {
return http.StatusInternalServerError
}
return e.statusCode
}
func (e *Error) PublicMessage() string {
if len(e.publicMessage) == 0 {
return "Internal error"
2019-08-19 18:05:34 +06:00
}
return e.publicMessage
}
func (e *Error) ShouldReport() bool {
return e.shouldReport
2019-08-19 18:05:34 +06:00
}
2021-04-26 17:52:50 +06:00
func (e *Error) StackTrace() []uintptr {
2019-08-19 18:05:34 +06:00
return e.stack
}
func (e *Error) Callers() []uintptr {
return e.stack
2017-10-05 01:44:58 +06:00
}
func (e *Error) Category() string {
if e.category == "" {
return defaultCategory
}
return e.category
}
func (e *Error) FormatStackLines() []string {
lines := make([]string, len(e.stack))
2019-08-19 18:05:34 +06:00
for i, pc := range e.stack {
f := runtime.FuncForPC(pc)
file, line := f.FileLine(pc)
lines[i] = fmt.Sprintf("%s:%d %s", file, line, f.Name())
2019-05-08 20:37:26 +06:00
}
return lines
}
func (e *Error) FormatStack() string {
return strings.Join(e.FormatStackLines(), "\n")
2017-10-05 01:44:58 +06:00
}
func Wrap(err error, stackSkip int, opts ...Option) *Error {
if err == nil {
return nil
}
var e *Error
2021-04-26 17:52:50 +06:00
if ierr, ok := err.(*Error); ok {
// if we have some options, we need to copy the error to not modify the original one
if len(opts) > 0 {
ecopy := *ierr
e = &ecopy
} else {
return ierr
}
} else {
e = &Error{
err: err,
shouldReport: true,
}
}
for _, opt := range opts {
opt(e)
}
if len(e.stack) == 0 {
e.stack = callers(stackSkip + 1)
2021-03-22 22:45:37 +06:00
}
return e
2021-03-22 22:45:37 +06:00
}
func WithStatusCode(code int) Option {
return func(e *Error) {
e.statusCode = code
2021-09-29 16:23:54 +06:00
}
}
func WithPublicMessage(msg string) Option {
return func(e *Error) {
e.publicMessage = msg
}
2019-08-19 18:05:34 +06:00
}
2017-10-05 01:44:58 +06:00
func WithPrefix(prefix string) Option {
return func(e *Error) {
if len(e.prefix) > 0 {
e.prefix = fmt.Sprintf("%s: %s", prefix, e.prefix)
} else {
e.prefix = prefix
}
2017-10-05 01:44:58 +06:00
}
}
2017-10-05 01:44:58 +06:00
func WithShouldReport(report bool) Option {
return func(e *Error) {
e.shouldReport = report
}
}
func WithCategory(category string) Option {
return func(e *Error) {
e.category = category
}
}
func callers(skip int) []uintptr {
stack := make([]uintptr, 10)
n := runtime.Callers(skip+2, stack)
return stack[:n]
2017-10-05 01:44:58 +06:00
}