diff --git a/internal/api/v1/file.go b/internal/api/v1/file.go index acaeabb..31a2223 100644 --- a/internal/api/v1/file.go +++ b/internal/api/v1/file.go @@ -48,7 +48,7 @@ func SetFileContent(w http.ResponseWriter, r *http.Request) { // no validation for include files if valErr != nil { - U.RespondJSON(w, r, valErr, http.StatusBadRequest) + U.RespondError(w, valErr, http.StatusBadRequest) return } diff --git a/internal/api/v1/utils/error.go b/internal/api/v1/utils/error.go index e2775df..5e72198 100644 --- a/internal/api/v1/utils/error.go +++ b/internal/api/v1/utils/error.go @@ -4,6 +4,7 @@ import ( "net/http" E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/utils/strutils/ansi" ) // HandleErr logs the error and returns an HTTP error response to the client. @@ -23,6 +24,13 @@ func HandleErr(w http.ResponseWriter, r *http.Request, origErr error, code ...in http.Error(w, http.StatusText(statusCode), statusCode) } +func RespondError(w http.ResponseWriter, err error, code ...int) { + if len(code) > 0 { + w.WriteHeader(code[0]) + } + WriteBody(w, []byte(ansi.StripANSI(err.Error()))) +} + func ErrMissingKey(k string) error { return E.New("missing key '" + k + "' in query or request body") } diff --git a/internal/api/v1/utils/utils.go b/internal/api/v1/utils/utils.go index 9cf97a8..94f9fb0 100644 --- a/internal/api/v1/utils/utils.go +++ b/internal/api/v1/utils/utils.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/yusing/go-proxy/internal/logging" + "github.com/yusing/go-proxy/internal/utils/strutils/ansi" ) func WriteBody(w http.ResponseWriter, body []byte) { @@ -27,13 +28,17 @@ func RespondJSON(w http.ResponseWriter, r *http.Request, data any, code ...int) j = []byte(fmt.Sprintf("%q", data)) case []byte: j = data + case error: + j, err = json.Marshal(ansi.StripANSI(data.Error())) default: j, err = json.MarshalIndent(data, "", " ") - if err != nil { - logging.Panic().Err(err).Msg("failed to marshal json") - return false - } } + + if err != nil { + logging.Panic().Err(err).Msg("failed to marshal json") + return false + } + _, err = w.Write(j) if err != nil { HandleErr(w, r, err) diff --git a/internal/config/config.go b/internal/config/config.go index 1127ef7..f1c42b7 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -67,8 +67,8 @@ func Load() (*Config, E.Error) { } func Validate(data []byte) E.Error { - var model *types.Config - return utils.DeserializeYAML(data, model) + var model types.Config + return utils.DeserializeYAML(data, &model) } func MatchDomains() []string { diff --git a/internal/route/provider/file.go b/internal/route/provider/file.go index 573f347..a06a7f7 100644 --- a/internal/route/provider/file.go +++ b/internal/route/provider/file.go @@ -31,8 +31,12 @@ func FileProviderImpl(filename string) (ProviderImpl, error) { return impl, nil } -func validate(data []byte) (route.RawEntries, E.Error) { - return utils.DeserializeYAMLMap[*route.RawEntry](data) +func validate(data []byte) (route.Routes, E.Error) { + entries, err := utils.DeserializeYAMLMap[*route.RawEntry](data) + if err != nil { + return route.NewRoutes(), err + } + return route.FromEntries(entries) } func Validate(data []byte) (err E.Error) { @@ -56,11 +60,7 @@ func (p *FileProvider) loadRoutesImpl() (route.Routes, E.Error) { return routes, E.From(err) } - entries, err := validate(data) - if err == nil { - return route.FromEntries(entries) - } - return routes, E.From(err) + return validate(data) } func (p *FileProvider) NewWatcher() W.Watcher { diff --git a/internal/utils/serialization.go b/internal/utils/serialization.go index 4d974d0..8fd7654 100644 --- a/internal/utils/serialization.go +++ b/internal/utils/serialization.go @@ -5,6 +5,7 @@ import ( "errors" "os" "reflect" + "runtime/debug" "strconv" "strings" "time" @@ -158,7 +159,7 @@ func Deserialize(src SerializedObject, dst any) E.Error { return E.Errorf("deserialize: src is %w", ErrNilValue) } if dst == nil { - return E.Errorf("deserialize: dst is %w", ErrNilValue) + return E.Errorf("deserialize: dst is %w\n%s", ErrNilValue, debug.Stack()) } dstV := reflect.ValueOf(dst) @@ -169,7 +170,7 @@ func Deserialize(src SerializedObject, dst any) E.Error { if dstV.CanSet() { dstV.Set(New(dstT.Elem())) } else { - return E.Errorf("deserialize: dst is %w", ErrNilValue) + return E.Errorf("deserialize: dst is %w\n%s", ErrNilValue, debug.Stack()) } } dstV = dstV.Elem() @@ -191,6 +192,9 @@ func Deserialize(src SerializedObject, dst any) E.Error { for _, field := range fields { var key string if jsonTag, ok := field.Tag.Lookup("json"); ok { + if jsonTag == "-" { + continue + } key = strutils.CommaSeperatedList(jsonTag)[0] } else { key = field.Name