diff --git a/internal/api/v1/utils/error.go b/internal/api/v1/utils/error.go index 574193e8..c7341e9c 100644 --- a/internal/api/v1/utils/error.go +++ b/internal/api/v1/utils/error.go @@ -1,10 +1,10 @@ package utils import ( + "encoding/json" "net/http" E "github.com/yusing/go-proxy/internal/error" - "github.com/yusing/go-proxy/internal/logging" "github.com/yusing/go-proxy/internal/utils/strutils/ansi" ) @@ -31,14 +31,13 @@ func RespondError(w http.ResponseWriter, err error, code ...int) { if len(code) == 0 { code = []int{http.StatusBadRequest} } - w.Header().Set("Content-Type", "text/html; charset=utf-8") - buf := make([]byte, 0, 100) - errMsg := err.Error() - buf, err = logging.FormatMessageToHTMLBytes(errMsg, buf) - if err != nil { - http.Error(w, ansi.StripANSI(errMsg), code[0]) + buf, err := json.Marshal(err) + if err != nil { // just in case + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + http.Error(w, ansi.StripANSI(err.Error()), code[0]) return } + w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(code[0]) _, _ = w.Write(buf) } diff --git a/internal/error/base.go b/internal/error/base.go index fea4382b..4668a118 100644 --- a/internal/error/base.go +++ b/internal/error/base.go @@ -1,6 +1,7 @@ package err import ( + "encoding/json" "errors" "fmt" ) @@ -46,3 +47,18 @@ func (err baseError) Withf(format string, args ...any) Error { func (err *baseError) Error() string { return err.Err.Error() } + +// MarshalJSON implements the json.Marshaler interface. +func (err *baseError) MarshalJSON() ([]byte, error) { + //nolint:errorlint + switch err := err.Err.(type) { + case Error, *withSubject: + return json.Marshal(err) + case json.Marshaler: + return err.MarshalJSON() + case interface{ MarshalText() ([]byte, error) }: + return err.MarshalText() + default: + return json.Marshal(err.Error()) + } +} diff --git a/internal/error/subject.go b/internal/error/subject.go index f080f11a..eac74995 100644 --- a/internal/error/subject.go +++ b/internal/error/subject.go @@ -1,6 +1,7 @@ package err import ( + "encoding/json" "strings" "github.com/yusing/go-proxy/internal/utils/strutils/ansi" @@ -8,8 +9,8 @@ import ( //nolint:errname type withSubject struct { - Subjects []string `json:"subjects"` - Err error `json:"err"` + Subjects []string + Err error pendingSubject string } @@ -74,7 +75,7 @@ func (err *withSubject) Error() string { for _, s := range err.Subjects { size += len(s) } - sb.Grow(size + 2 + n*len(subjectSep) + len(errStr)) + sb.Grow(size + 2 + n*len(subjectSep) + len(errStr) + len(highlight(""))) for i := n - 1; i > 0; i-- { sb.WriteString(err.Subjects[i]) @@ -85,3 +86,20 @@ func (err *withSubject) Error() string { sb.WriteString(errStr) return sb.String() } + +// MarshalJSON implements the json.Marshaler interface. +func (err *withSubject) MarshalJSON() ([]byte, error) { + subjects := make([]string, len(err.Subjects)) + for i, s := range err.Subjects { + subjects[len(err.Subjects)-i-1] = s + } + reversed := struct { + Subjects []string `json:"subjects"` + Err error `json:"err"` + }{ + Subjects: subjects, + Err: err.Err, + } + + return json.Marshal(reversed) +}