From 361931ed962a373c7bd0e5cb85d8f6457f5cbdde Mon Sep 17 00:00:00 2001 From: yusing Date: Fri, 28 Mar 2025 06:26:36 +0800 Subject: [PATCH] refactor: rename module 'err' to 'gperr' in references --- internal/config/config.go | 36 ++++++------ internal/config/types/config.go | 4 +- internal/docker/label.go | 10 ++-- internal/notif/base.go | 14 ++--- internal/notif/config.go | 10 ++-- internal/notif/dispatcher.go | 22 ++------ internal/notif/ntfy.go | 12 ++-- internal/notif/providers.go | 12 ++-- internal/notif/webhook.go | 16 +++--- internal/route/fileserver.go | 15 ++--- internal/route/provider/docker.go | 19 +++---- internal/route/provider/event_handler.go | 21 ++++--- internal/route/provider/file.go | 14 ++--- internal/route/provider/provider.go | 18 +++--- internal/route/reverse_proxy.go | 11 ++-- internal/route/route.go | 19 ++++--- internal/route/rules/cache.go | 4 +- internal/route/rules/do.go | 20 +++---- internal/route/rules/errors.go | 26 +++++---- internal/route/rules/on.go | 8 +-- internal/route/rules/on_test.go | 4 +- internal/route/rules/parser.go | 4 +- internal/route/rules/parser_test.go | 4 +- internal/route/rules/validate.go | 30 +++++----- internal/route/stream.go | 12 ++-- internal/route/types/port.go | 8 +-- internal/route/types/scheme.go | 6 +- internal/route/udp_forwarder.go | 4 +- internal/task/task.go | 4 +- internal/utils/io.go | 6 +- internal/utils/serialization.go | 64 +++++++++++----------- internal/utils/validation.go | 6 +- internal/watcher/directory_watcher.go | 12 ++-- internal/watcher/docker_watcher.go | 8 +-- internal/watcher/events/event_queue.go | 8 +-- internal/watcher/file_watcher.go | 6 +- internal/watcher/health/monitor/monitor.go | 8 +-- internal/watcher/watcher.go | 4 +- 38 files changed, 242 insertions(+), 267 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index c086156b..20d66030 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -13,7 +13,7 @@ import ( "github.com/yusing/go-proxy/internal/common" "github.com/yusing/go-proxy/internal/config/types" "github.com/yusing/go-proxy/internal/entrypoint" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/logging" "github.com/yusing/go-proxy/internal/net/http/server" "github.com/yusing/go-proxy/internal/notif" @@ -64,7 +64,7 @@ func newConfig() *Config { } } -func Load() (*Config, E.Error) { +func Load() (*Config, gperr.Error) { if instance != nil { return instance, nil } @@ -83,8 +83,8 @@ func WatchChanges() { t, configEventFlushInterval, OnConfigChange, - func(err E.Error) { - E.LogError("config reload error", err) + func(err gperr.Error) { + gperr.LogError("config reload error", err) }, ) eventQueue.Start(cfgWatcher.Events(t.Context())) @@ -108,7 +108,7 @@ func OnConfigChange(ev []events.Event) { } } -func Reload() E.Error { +func Reload() gperr.Error { // avoid race between config change and API reload request reloadMu.Lock() defer reloadMu.Unlock() @@ -117,7 +117,7 @@ func Reload() E.Error { err := newCfg.load() if err != nil { newCfg.task.Finish(err) - return E.New("using last config").With(err) + return gperr.New("using last config").With(err) } // cancel all current subtasks -> wait @@ -132,7 +132,7 @@ func (cfg *Config) Value() *types.Config { return instance.value } -func (cfg *Config) Reload() E.Error { +func (cfg *Config) Reload() gperr.Error { return Reload() } @@ -162,20 +162,20 @@ func (cfg *Config) StartAutoCert() { } if err := autocert.Setup(); err != nil { - E.LogFatal("autocert setup error", err) + gperr.LogFatal("autocert setup error", err) } else { autocert.ScheduleRenewal(cfg.task) } } func (cfg *Config) StartProxyProviders() { - errs := cfg.providers.CollectErrorsParallel( + errs := cfg.providers.CollectErrors( func(_ string, p *proxy.Provider) error { return p.Start(cfg.task) }) - if err := E.Join(errs...); err != nil { - E.LogError("route provider errors", err) + if err := gperr.Join(errs...); err != nil { + gperr.LogError("route provider errors", err) } } @@ -209,21 +209,21 @@ func (cfg *Config) StartServers(opts ...*StartServersOptions) { } } -func (cfg *Config) load() E.Error { +func (cfg *Config) load() gperr.Error { const errMsg = "config load error" data, err := os.ReadFile(common.ConfigPath) if err != nil { - E.LogFatal(errMsg, err) + gperr.LogFatal(errMsg, err) } model := types.DefaultConfig() if err := utils.DeserializeYAML(data, model); err != nil { - E.LogFatal(errMsg, err) + gperr.LogFatal(errMsg, err) } // errors are non fatal below - errs := E.NewBuilder(errMsg) + errs := gperr.NewBuilder(errMsg) errs.Add(cfg.entrypoint.SetMiddlewares(model.Entrypoint.Middlewares)) errs.Add(cfg.entrypoint.SetAccessLogger(cfg.task, model.Entrypoint.AccessLog)) cfg.initNotification(model.Providers.Notification) @@ -251,7 +251,7 @@ func (cfg *Config) initNotification(notifCfg []notif.NotificationConfig) { } } -func (cfg *Config) initAutoCert(autocertCfg *autocert.AutocertConfig) (err E.Error) { +func (cfg *Config) initAutoCert(autocertCfg *autocert.AutocertConfig) (err gperr.Error) { if cfg.autocertProvider != nil { return } @@ -260,9 +260,7 @@ func (cfg *Config) initAutoCert(autocertCfg *autocert.AutocertConfig) (err E.Err return } -func (cfg *Config) loadRouteProviders(providers *types.Providers) E.Error { - errs := E.NewBuilder("route provider errors") - results := E.NewBuilder("loaded route providers") +func (cfg *Config) loadRouteProviders(providers *config.Providers) gperr.Error { lenLongestName := 0 for _, filename := range providers.Files { diff --git a/internal/config/types/config.go b/internal/config/types/config.go index e7a7e3de..7c8ed988 100644 --- a/internal/config/types/config.go +++ b/internal/config/types/config.go @@ -6,7 +6,7 @@ import ( "github.com/go-playground/validator/v10" "github.com/yusing/go-proxy/internal/autocert" - "github.com/yusing/go-proxy/internal/net/http/accesslog" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/notif" "github.com/yusing/go-proxy/internal/utils" @@ -34,7 +34,7 @@ type ( ConfigInstance interface { Value() *Config - Reload() E.Error + Reload() gperr.Error Statistics() map[string]any RouteProviderList() []string Context() context.Context diff --git a/internal/docker/label.go b/internal/docker/label.go index 2dead0a1..73de8232 100644 --- a/internal/docker/label.go +++ b/internal/docker/label.go @@ -1,17 +1,17 @@ package docker import ( - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/utils/strutils" ) type LabelMap = map[string]any -var ErrInvalidLabel = E.New("invalid label") +var ErrInvalidLabel = gperr.New("invalid label") -func ParseLabels(labels map[string]string) (LabelMap, E.Error) { +func ParseLabels(labels map[string]string) (LabelMap, gperr.Error) { nestedMap := make(LabelMap) - errs := E.NewBuilder("labels error") + errs := gperr.NewBuilder("labels error") for lbl, value := range labels { parts := strutils.SplitRune(lbl, '.') @@ -37,7 +37,7 @@ func ParseLabels(labels map[string]string) (LabelMap, E.Error) { // Move deeper into the nested map m, ok := currentMap[k].(LabelMap) if !ok && currentMap[k] != "" { - errs.Add(E.Errorf("expect mapping, got %T", currentMap[k]).Subject(lbl)) + errs.Add(gperr.Errorf("expect mapping, got %T", currentMap[k]).Subject(lbl)) continue } else if !ok { m = make(LabelMap) diff --git a/internal/notif/base.go b/internal/notif/base.go index 5af0df18..a1db3af3 100644 --- a/internal/notif/base.go +++ b/internal/notif/base.go @@ -6,7 +6,7 @@ import ( "net/url" "strings" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" ) type ProviderBase struct { @@ -16,12 +16,12 @@ type ProviderBase struct { } var ( - ErrMissingToken = E.New("token is required") - ErrURLMissingScheme = E.New("url missing scheme, expect 'http://' or 'https://'") + ErrMissingToken = gperr.New("token is required") + ErrURLMissingScheme = gperr.New("url missing scheme, expect 'http://' or 'https://'") ) // Validate implements the utils.CustomValidator interface. -func (base *ProviderBase) Validate() E.Error { +func (base *ProviderBase) Validate() gperr.Error { if base.Token == "" { return ErrMissingToken } @@ -30,7 +30,7 @@ func (base *ProviderBase) Validate() E.Error { } u, err := url.Parse(base.URL) if err != nil { - return E.Wrap(err) + return gperr.Wrap(err) } base.URL = u.String() return nil @@ -63,7 +63,7 @@ func (base *ProviderBase) SetHeaders(logMsg *LogMessage, headers http.Header) { func (base *ProviderBase) makeRespError(resp *http.Response) error { body, err := io.ReadAll(resp.Body) if err == nil { - return E.Errorf("%s status %d: %s", base.Name, resp.StatusCode, body) + return gperr.Errorf("%s status %d: %s", base.Name, resp.StatusCode, body) } - return E.Errorf("%s status %d", base.Name, resp.StatusCode) + return gperr.Errorf("%s status %d", base.Name, resp.StatusCode) } diff --git a/internal/notif/config.go b/internal/notif/config.go index c9c29cd4..1f35cdb5 100644 --- a/internal/notif/config.go +++ b/internal/notif/config.go @@ -1,7 +1,7 @@ package notif import ( - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/utils" ) @@ -11,13 +11,13 @@ type NotificationConfig struct { } var ( - ErrMissingNotifProvider = E.New("missing notification provider") - ErrInvalidNotifProviderType = E.New("invalid notification provider type") - ErrUnknownNotifProvider = E.New("unknown notification provider") + ErrMissingNotifProvider = gperr.New("missing notification provider") + ErrInvalidNotifProviderType = gperr.New("invalid notification provider type") + ErrUnknownNotifProvider = gperr.New("unknown notification provider") ) // UnmarshalMap implements MapUnmarshaler. -func (cfg *NotificationConfig) UnmarshalMap(m map[string]any) (err E.Error) { +func (cfg *NotificationConfig) UnmarshalMap(m map[string]any) (err gperr.Error) { // extract provider name providerName := m["provider"] switch providerName := providerName.(type) { diff --git a/internal/notif/dispatcher.go b/internal/notif/dispatcher.go index c8431b25..fd138e52 100644 --- a/internal/notif/dispatcher.go +++ b/internal/notif/dispatcher.go @@ -2,7 +2,7 @@ package notif import ( "github.com/rs/zerolog" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/logging" "github.com/yusing/go-proxy/internal/task" F "github.com/yusing/go-proxy/internal/utils/functional" @@ -89,29 +89,15 @@ func (disp *Dispatcher) dispatch(msg *LogMessage) { task := disp.task.Subtask("dispatcher") defer task.Finish("notif dispatched") - errs := E.NewBuilder(dispatchErr) + errs := gperr.NewBuilder(dispatchErr) disp.providers.RangeAllParallel(func(p Provider) { if err := notifyProvider(task.Context(), p, msg); err != nil { - errs.Add(E.PrependSubject(p.GetName(), err)) + errs.Add(gperr.PrependSubject(p.GetName(), err)) } }) if errs.HasError() { - E.LogError(errs.About(), errs.Error()) + gperr.LogError(errs.About(), errs.Error()) } else { logging.Debug().Str("title", msg.Title).Msgf("dispatched notif") } } - -// Run implements zerolog.Hook. -// func (disp *Dispatcher) Run(e *zerolog.Event, level zerolog.Level, message string) { -// if strings.HasPrefix(message, dispatchErr) { // prevent recursion -// return -// } -// switch level { -// case zerolog.WarnLevel, zerolog.ErrorLevel, zerolog.FatalLevel, zerolog.PanicLevel: -// disp.logCh <- &LogMessage{ -// Level: level, -// Message: message, -// } -// } -// } diff --git a/internal/notif/ntfy.go b/internal/notif/ntfy.go index 42b97f76..6e10725d 100644 --- a/internal/notif/ntfy.go +++ b/internal/notif/ntfy.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/rs/zerolog" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" ) // See https://docs.ntfy.sh/publish @@ -24,22 +24,22 @@ const ( NtfyStylePlain NtfyStyle = "plain" ) -func (n *Ntfy) Validate() E.Error { +func (n *Ntfy) Validate() gperr.Error { if n.URL == "" { - return E.New("url is required") + return gperr.New("url is required") } if n.Topic == "" { - return E.New("topic is required") + return gperr.New("topic is required") } if n.Topic[0] == '/' { - return E.New("topic should not start with a slash") + return gperr.New("topic should not start with a slash") } switch n.Style { case "": n.Style = NtfyStyleMarkdown case NtfyStyleMarkdown, NtfyStylePlain: default: - return E.Errorf("invalid style, expecting %q or %q, got %q", NtfyStyleMarkdown, NtfyStylePlain, n.Style) + return gperr.Errorf("invalid style, expecting %q or %q, got %q", NtfyStyleMarkdown, NtfyStylePlain, n.Style) } return nil } diff --git a/internal/notif/providers.go b/internal/notif/providers.go index 0de2a2cf..953fb3b6 100644 --- a/internal/notif/providers.go +++ b/internal/notif/providers.go @@ -6,8 +6,8 @@ import ( "net/http" "time" - E "github.com/yusing/go-proxy/internal/error" - gphttp "github.com/yusing/go-proxy/internal/net/http" + "github.com/yusing/go-proxy/internal/gperr" + gphttp "github.com/yusing/go-proxy/internal/net/gphttp" "github.com/yusing/go-proxy/internal/utils" ) @@ -26,7 +26,7 @@ type ( makeRespError(resp *http.Response) error } - ProviderCreateFunc func(map[string]any) (Provider, E.Error) + ProviderCreateFunc func(map[string]any) (Provider, gperr.Error) ProviderConfig map[string]any ) @@ -39,7 +39,7 @@ const ( func notifyProvider(ctx context.Context, provider Provider, msg *LogMessage) error { body, err := provider.MakeBody(msg) if err != nil { - return E.PrependSubject(provider.GetName(), err) + return gperr.PrependSubject(provider.GetName(), err) } ctx, cancel := context.WithTimeout(ctx, 2*time.Second) @@ -52,7 +52,7 @@ func notifyProvider(ctx context.Context, provider Provider, msg *LogMessage) err body, ) if err != nil { - return E.PrependSubject(provider.GetName(), err) + return gperr.PrependSubject(provider.GetName(), err) } req.Header.Set("Content-Type", provider.GetMIMEType()) @@ -63,7 +63,7 @@ func notifyProvider(ctx context.Context, provider Provider, msg *LogMessage) err resp, err := http.DefaultClient.Do(req) if err != nil { - return E.PrependSubject(provider.GetName(), err) + return gperr.PrependSubject(provider.GetName(), err) } defer resp.Body.Close() diff --git a/internal/notif/webhook.go b/internal/notif/webhook.go index 806b5f94..13fd23ca 100644 --- a/internal/notif/webhook.go +++ b/internal/notif/webhook.go @@ -8,7 +8,7 @@ import ( "net/http" "strings" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" ) type Webhook struct { @@ -27,7 +27,7 @@ var webhookTemplates = map[string]string{ "discord": discordPayload, } -func (webhook *Webhook) Validate() E.Error { +func (webhook *Webhook) Validate() gperr.Error { if err := webhook.ProviderBase.Validate(); err != nil && !err.Is(ErrMissingToken) { return err } @@ -37,16 +37,16 @@ func (webhook *Webhook) Validate() E.Error { webhook.MIMEType = "application/json" case "application/json", "application/x-www-form-urlencoded", "text/plain": default: - return E.New("invalid mime_type, expect empty, 'application/json', 'application/x-www-form-urlencoded' or 'text/plain'") + return gperr.New("invalid mime_type, expect empty, 'application/json', 'application/x-www-form-urlencoded' or 'text/plain'") } switch webhook.Template { case "": if webhook.MIMEType == "application/json" && !json.Valid([]byte(webhook.Payload)) { - return E.New("invalid payload, expect valid JSON") + return gperr.New("invalid payload, expect valid JSON") } if webhook.Payload == "" { - return E.New("invalid payload, expect non-empty") + return gperr.New("invalid payload, expect non-empty") } case "discord": webhook.ColorMode = "dec" @@ -56,7 +56,7 @@ func (webhook *Webhook) Validate() E.Error { webhook.Payload = discordPayload } default: - return E.New("invalid template, expect empty or 'discord'") + return gperr.New("invalid template, expect empty or 'discord'") } switch webhook.Method { @@ -64,7 +64,7 @@ func (webhook *Webhook) Validate() E.Error { webhook.Method = http.MethodPost case http.MethodGet, http.MethodPost, http.MethodPut: default: - return E.New("invalid method, expect empty, 'GET', 'POST' or 'PUT'") + return gperr.New("invalid method, expect empty, 'GET', 'POST' or 'PUT'") } switch webhook.ColorMode { @@ -72,7 +72,7 @@ func (webhook *Webhook) Validate() E.Error { webhook.ColorMode = "hex" case "hex", "dec": default: - return E.New("invalid color_mode, expect empty, 'hex' or 'dec'") + return gperr.New("invalid color_mode, expect empty, 'hex' or 'dec'") } return nil diff --git a/internal/route/fileserver.go b/internal/route/fileserver.go index 8d45c4d4..b39847de 100644 --- a/internal/route/fileserver.go +++ b/internal/route/fileserver.go @@ -6,10 +6,7 @@ import ( "path/filepath" "github.com/yusing/go-proxy/internal/common" - gphttp "github.com/yusing/go-proxy/internal/net/http" - "github.com/yusing/go-proxy/internal/net/http/accesslog" - "github.com/yusing/go-proxy/internal/net/http/middleware" - metricslogger "github.com/yusing/go-proxy/internal/net/http/middleware/metrics_logger" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/route/routes" "github.com/yusing/go-proxy/internal/task" "github.com/yusing/go-proxy/internal/watcher/health" @@ -35,12 +32,12 @@ func handler(root string) http.Handler { return http.FileServer(http.Dir(root)) } -func NewFileServer(base *Route) (*FileServer, E.Error) { +func NewFileServer(base *Route) (*FileServer, gperr.Error) { s := &FileServer{Route: base} s.Root = filepath.Clean(s.Root) if !path.IsAbs(s.Root) { - return nil, E.New("`root` must be an absolute path") + return nil, gperr.New("`root` must be an absolute path") } s.handler = handler(s.Root) @@ -57,7 +54,7 @@ func NewFileServer(base *Route) (*FileServer, E.Error) { } // Start implements task.TaskStarter. -func (s *FileServer) Start(parent task.Parent) E.Error { +func (s *FileServer) Start(parent task.Parent) gperr.Error { s.task = parent.Subtask("fileserver."+s.TargetName(), false) pathPatterns := s.PathPatterns @@ -66,7 +63,7 @@ func (s *FileServer) Start(parent task.Parent) E.Error { case len(pathPatterns) == 1 && pathPatterns[0] == "/": default: mux := gphttp.NewServeMux() - patErrs := E.NewBuilder("invalid path pattern(s)") + patErrs := gperr.NewBuilder("invalid path pattern(s)") for _, p := range pathPatterns { patErrs.Add(mux.Handle(p, s.handler)) } @@ -88,7 +85,7 @@ func (s *FileServer) Start(parent task.Parent) E.Error { s.accessLogger, err = accesslog.NewFileAccessLogger(s.task, s.AccessLog) if err != nil { s.task.Finish(err) - return E.Wrap(err) + return gperr.Wrap(err) } } diff --git a/internal/route/provider/docker.go b/internal/route/provider/docker.go index 90c0c160..5fd33a10 100755 --- a/internal/route/provider/docker.go +++ b/internal/route/provider/docker.go @@ -8,7 +8,7 @@ import ( "github.com/rs/zerolog" "github.com/yusing/go-proxy/internal/common" "github.com/yusing/go-proxy/internal/docker" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/logging" "github.com/yusing/go-proxy/internal/route" U "github.com/yusing/go-proxy/internal/utils" @@ -27,7 +27,7 @@ const ( aliasRefPrefixAlt = '$' ) -var ErrAliasRefIndexOutOfRange = E.New("index out of range") +var ErrAliasRefIndexOutOfRange = gperr.New("index out of range") func DockerProviderImpl(name, dockerHost string) (ProviderImpl, error) { if dockerHost == common.DockerHostFromEnv { @@ -60,13 +60,12 @@ func (p *DockerProvider) NewWatcher() watcher.Watcher { return watcher.NewDockerWatcher(p.dockerHost) } -func (p *DockerProvider) loadRoutesImpl() (route.Routes, E.Error) { - containers, err := docker.ListContainers(p.dockerHost) +func (p *DockerProvider) loadRoutesImpl() (route.Routes, gperr.Error) { if err != nil { - return nil, E.From(err) + return nil, gperr.Wrap(err) } - errs := E.NewBuilder("") + errs := gperr.NewBuilder("") routes := make(route.Routes) for _, c := range containers { @@ -93,7 +92,7 @@ func (p *DockerProvider) loadRoutesImpl() (route.Routes, E.Error) { // Returns a list of proxy entries for a container. // Always non-nil. -func (p *DockerProvider) routesFromContainerLabels(container *docker.Container) (route.Routes, E.Error) { +func (p *DockerProvider) routesFromContainerLabels(container *docker.Container) (route.Routes, gperr.Error) { if !container.IsExplicit && p.IsExplicitOnly() { return nil, nil } @@ -109,7 +108,7 @@ func (p *DockerProvider) routesFromContainerLabels(container *docker.Container) } } - errs := E.NewBuilder("label errors") + errs := gperr.NewBuilder("label errors") m, err := docker.ParseLabels(container.Labels) errs.Add(err) @@ -118,7 +117,7 @@ func (p *DockerProvider) routesFromContainerLabels(container *docker.Container) for alias, entryMapAny := range m { if len(alias) == 0 { - errs.Add(E.New("empty alias")) + errs.Add(gperr.New("empty alias")) continue } @@ -132,7 +131,7 @@ func (p *DockerProvider) routesFromContainerLabels(container *docker.Container) panic(fmt.Errorf("invalid entry map type %T", entryMapAny)) } if err := yaml.Unmarshal([]byte(yamlStr), &entryMap); err != nil { - errs.Add(E.From(err).Subject(alias)) + errs.Add(gperr.Wrap(err).Subject(alias)) continue } } diff --git a/internal/route/provider/event_handler.go b/internal/route/provider/event_handler.go index 9e132d5a..522df4ad 100644 --- a/internal/route/provider/event_handler.go +++ b/internal/route/provider/event_handler.go @@ -1,8 +1,7 @@ package provider import ( - "github.com/yusing/go-proxy/internal/common" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/route" "github.com/yusing/go-proxy/internal/route/provider/types" "github.com/yusing/go-proxy/internal/task" @@ -12,19 +11,19 @@ import ( type EventHandler struct { provider *Provider - errs *E.Builder - added *E.Builder - removed *E.Builder - updated *E.Builder + errs *gperr.Builder + added *gperr.Builder + removed *gperr.Builder + updated *gperr.Builder } func (p *Provider) newEventHandler() *EventHandler { return &EventHandler{ provider: p, - errs: E.NewBuilder("event errors"), - added: E.NewBuilder("added"), - removed: E.NewBuilder("removed"), - updated: E.NewBuilder("updated"), + errs: gperr.NewBuilder("event errors"), + added: gperr.NewBuilder("added"), + removed: gperr.NewBuilder("removed"), + updated: gperr.NewBuilder("updated"), } } @@ -121,7 +120,7 @@ func (handler *EventHandler) Update(parent task.Parent, oldRoute *route.Route, n } func (handler *EventHandler) Log() { - results := E.NewBuilder("event occurred") + results := gperr.NewBuilder("event occurred") results.AddFrom(handler.added, false) results.AddFrom(handler.removed, false) results.AddFrom(handler.updated, false) diff --git a/internal/route/provider/file.go b/internal/route/provider/file.go index 8d2e2086..79855b93 100644 --- a/internal/route/provider/file.go +++ b/internal/route/provider/file.go @@ -7,7 +7,7 @@ import ( "github.com/rs/zerolog" "github.com/yusing/go-proxy/internal/common" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/logging" "github.com/yusing/go-proxy/internal/route" "github.com/yusing/go-proxy/internal/utils" @@ -33,12 +33,12 @@ func FileProviderImpl(filename string) (ProviderImpl, error) { return impl, nil } -func validate(data []byte) (routes route.Routes, err E.Error) { +func validate(data []byte) (routes route.Routes, err gperr.Error) { err = utils.DeserializeYAML(data, &routes) return } -func Validate(data []byte) (err E.Error) { +func Validate(data []byte) (err gperr.Error) { _, err = validate(data) return } @@ -59,16 +59,16 @@ func (p *FileProvider) Logger() *zerolog.Logger { return &p.l } -func (p *FileProvider) loadRoutesImpl() (route.Routes, E.Error) { +func (p *FileProvider) loadRoutesImpl() (route.Routes, gperr.Error) { data, err := os.ReadFile(p.path) if err != nil { - return nil, E.Wrap(err) + return nil, gperr.Wrap(err) } routes, err := validate(data) if err != nil && len(routes) == 0 { - return nil, E.Wrap(err) + return nil, gperr.Wrap(err) } - return routes, E.Wrap(err) + return routes, gperr.Wrap(err) } func (p *FileProvider) NewWatcher() W.Watcher { diff --git a/internal/route/provider/provider.go b/internal/route/provider/provider.go index 6e94b285..e41ad129 100644 --- a/internal/route/provider/provider.go +++ b/internal/route/provider/provider.go @@ -7,7 +7,7 @@ import ( "time" "github.com/rs/zerolog" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/route" "github.com/yusing/go-proxy/internal/route/provider/types" "github.com/yusing/go-proxy/internal/task" @@ -28,7 +28,7 @@ type ( fmt.Stringer ShortName() string IsExplicitOnly() bool - loadRoutesImpl() (route.Routes, E.Error) + loadRoutesImpl() (route.Routes, gperr.Error) NewWatcher() W.Watcher Logger() *zerolog.Logger } @@ -92,10 +92,10 @@ func (p *Provider) startRoute(parent task.Parent, r *route.Route) E.Error { } // Start implements task.TaskStarter. -func (p *Provider) Start(parent task.Parent) E.Error { +func (p *Provider) Start(parent task.Parent) gperr.Error { t := parent.Subtask("provider."+p.String(), false) - errs := E.NewBuilder("routes error") + errs := gperr.NewBuilder("routes error") for _, r := range p.routes { errs.Add(p.startRoute(t, r)) } @@ -109,8 +109,8 @@ func (p *Provider) Start(parent task.Parent) E.Error { handler.Handle(t, events) handler.Log() }, - func(err E.Error) { - E.LogError("event error", err, p.Logger()) + func(err gperr.Error) { + gperr.LogError("event error", err, p.Logger()) }, ) eventQueue.Start(p.watcher.Events(t.Context())) @@ -132,12 +132,12 @@ func (p *Provider) GetRoute(alias string) (r *route.Route, ok bool) { return } -func (p *Provider) loadRoutes() (routes route.Routes, err E.Error) { +func (p *Provider) loadRoutes() (routes route.Routes, err gperr.Error) { routes, err = p.loadRoutesImpl() if err != nil && len(routes) == 0 { return route.Routes{}, err } - errs := E.NewBuilder("routes error") + errs := gperr.NewBuilder("routes error") errs.Add(err) // check for exclusion // set alias and provider, then validate @@ -156,7 +156,7 @@ func (p *Provider) loadRoutes() (routes route.Routes, err E.Error) { return routes, errs.Error() } -func (p *Provider) LoadRoutes() (err E.Error) { +func (p *Provider) LoadRoutes() (err gperr.Error) { p.routes, err = p.loadRoutes() return } diff --git a/internal/route/reverse_proxy.go b/internal/route/reverse_proxy.go index a80b94b3..9631f346 100755 --- a/internal/route/reverse_proxy.go +++ b/internal/route/reverse_proxy.go @@ -7,7 +7,7 @@ import ( "github.com/yusing/go-proxy/internal/common" "github.com/yusing/go-proxy/internal/docker" "github.com/yusing/go-proxy/internal/docker/idlewatcher" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/logging" gphttp "github.com/yusing/go-proxy/internal/net/http" "github.com/yusing/go-proxy/internal/net/http/accesslog" @@ -38,8 +38,7 @@ type ( // var globalMux = http.NewServeMux() // TODO: support regex subdomain matching. -func NewReverseProxyRoute(base *Route) (*ReveseProxyRoute, E.Error) { - trans := gphttp.DefaultTransport +func NewReverseProxyRoute(base *Route) (*ReveseProxyRoute, gperr.Error) { httpConfig := base.HTTPConfig if httpConfig.NoTLSVerify { @@ -72,7 +71,7 @@ func (r *ReveseProxyRoute) String() string { } // Start implements task.TaskStarter. -func (r *ReveseProxyRoute) Start(parent task.Parent) E.Error { +func (r *ReveseProxyRoute) Start(parent task.Parent) gperr.Error { r.task = parent.Subtask("http."+r.TargetName(), false) switch { @@ -103,7 +102,7 @@ func (r *ReveseProxyRoute) Start(parent task.Parent) E.Error { r.rp.AccessLogger, err = accesslog.NewFileAccessLogger(r.task, r.AccessLog) if err != nil { r.task.Finish(err) - return E.From(err) + return gperr.Wrap(err) } } @@ -119,7 +118,7 @@ func (r *ReveseProxyRoute) Start(parent task.Parent) E.Error { Str("route", r.TargetName()). Msg("`path_patterns` for reverse proxy is deprecated. Use `rules` instead.") mux := gphttp.NewServeMux() - patErrs := E.NewBuilder("invalid path pattern(s)") + patErrs := gperr.NewBuilder("invalid path pattern(s)") for _, p := range pathPatterns { patErrs.Add(mux.HandleFunc(p, r.rp.HandlerFunc)) } diff --git a/internal/route/route.go b/internal/route/route.go index 4aac782f..57466753 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -7,12 +7,12 @@ import ( "github.com/yusing/go-proxy/internal/docker" idlewatcher "github.com/yusing/go-proxy/internal/docker/idlewatcher/types" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/homepage" net "github.com/yusing/go-proxy/internal/net/types" "github.com/yusing/go-proxy/internal/task" "github.com/yusing/go-proxy/internal/watcher/health" - dockertypes "github.com/docker/docker/api/types" "github.com/yusing/go-proxy/internal/common" E "github.com/yusing/go-proxy/internal/error" "github.com/yusing/go-proxy/internal/net/http/accesslog" @@ -65,14 +65,14 @@ func (r Routes) Contains(alias string) bool { return ok } -func (r *Route) Validate() (err E.Error) { +func (r *Route) Validate() (err gperr.Error) { if r.isValidated { return nil } r.isValidated = true r.Finalize() - errs := E.NewBuilder("entry validation failed") + errs := gperr.NewBuilder("entry validation failed") switch r.Scheme { case types.SchemeFileServer: @@ -86,18 +86,18 @@ func (r *Route) Validate() (err E.Error) { } fallthrough case types.SchemeTCP, types.SchemeUDP: - r.LisURL = E.Collect(errs, net.ParseURL, fmt.Sprintf("%s://%s:%d", r.Scheme, r.Host, r.Port.Listening)) + r.LisURL = gperr.Collect(errs, net.ParseURL, fmt.Sprintf("%s://:%d", r.Scheme, r.Port.Listening)) fallthrough default: if r.LoadBalance != nil && r.LoadBalance.Link == "" { r.LoadBalance = nil } - r.ProxyURL = E.Collect(errs, net.ParseURL, fmt.Sprintf("%s://%s:%d", r.Scheme, r.Host, r.Port.Proxy)) - r.Idlewatcher = E.Collect(errs, idlewatcher.ValidateConfig, r.Container) + r.ProxyURL = gperr.Collect(errs, net.ParseURL, fmt.Sprintf("%s://%s:%d", r.Scheme, r.Host, r.Port.Proxy)) + r.Idlewatcher = gperr.Collect(errs, idlewatcher.ValidateConfig, r.Container) } if !r.UseHealthCheck() && (r.UseLoadBalance() || r.UseIdleWatcher()) { - errs.Adds("healthCheck.disable cannot be true when loadbalancer or idlewatcher is enabled") + errs.Adds("cannot disable healthcheck when loadbalancer or idle watcher is enabled") } if errs.HasError() { @@ -118,10 +118,11 @@ func (r *Route) Validate() (err E.Error) { return err } -func (r *Route) Start(parent task.Parent) (err E.Error) { +func (r *Route) Start(parent task.Parent) (err gperr.Error) { if r.impl == nil { - return E.New("route not initialized") + return gperr.New("route not initialized") } + return r.impl.Start(parent) } diff --git a/internal/route/rules/cache.go b/internal/route/rules/cache.go index 532f5087..c57965ab 100644 --- a/internal/route/rules/cache.go +++ b/internal/route/rules/cache.go @@ -41,9 +41,7 @@ func NewCache() Cache { // Release clear the contents of the Cached and returns it to the pool. func (c Cache) Release() { - for _, k := range cacheKeys { - delete(c, k) - } + clear(c) cachePool.Put(c) } diff --git a/internal/route/rules/do.go b/internal/route/rules/do.go index 978a9e94..f00c20d3 100644 --- a/internal/route/rules/do.go +++ b/internal/route/rules/do.go @@ -6,9 +6,9 @@ import ( "strconv" "strings" - E "github.com/yusing/go-proxy/internal/error" - gphttp "github.com/yusing/go-proxy/internal/net/http" - "github.com/yusing/go-proxy/internal/net/http/reverseproxy" + "github.com/yusing/go-proxy/internal/gperr" + gphttp "github.com/yusing/go-proxy/internal/net/gphttp" + "github.com/yusing/go-proxy/internal/net/gphttp/reverseproxy" "github.com/yusing/go-proxy/internal/net/types" "github.com/yusing/go-proxy/internal/utils/strutils" ) @@ -47,7 +47,7 @@ var commands = map[string]struct { "to": "the path to rewrite to, must start with /", }, }, - validate: func(args []string) (any, E.Error) { + validate: func(args []string) (any, gperr.Error) { if len(args) != 2 { return nil, ErrExpectTwoArgs } @@ -109,7 +109,7 @@ var commands = map[string]struct { "text": "the error message to return", }, }, - validate: func(args []string) (any, E.Error) { + validate: func(args []string) (any, gperr.Error) { if len(args) != 2 { return nil, ErrExpectTwoArgs } @@ -137,7 +137,7 @@ var commands = map[string]struct { "realm": "the authentication realm", }, }, - validate: func(args []string) (any, E.Error) { + validate: func(args []string) (any, gperr.Error) { if len(args) == 1 { return args[0], nil } @@ -164,7 +164,7 @@ var commands = map[string]struct { if target.Scheme == "" { target.Scheme = "http" } - rp := reverseproxy.NewReverseProxy("", target, gphttp.DefaultTransport) + rp := reverseproxy.NewReverseProxy("", target, gphttp.NewTransport()) return ReturningCommand(rp.ServeHTTP) }, }, @@ -176,7 +176,7 @@ var commands = map[string]struct { "value": "the value to set", }, }, - validate: func(args []string) (any, E.Error) { + validate: func(args []string) (any, gperr.Error) { return validateModField(ModFieldSet, args) }, build: func(args any) CommandHandler { @@ -191,7 +191,7 @@ var commands = map[string]struct { "value": "the value to add", }, }, - validate: func(args []string) (any, E.Error) { + validate: func(args []string) (any, gperr.Error) { return validateModField(ModFieldAdd, args) }, build: func(args any) CommandHandler { @@ -205,7 +205,7 @@ var commands = map[string]struct { "field": "the field to remove", }, }, - validate: func(args []string) (any, E.Error) { + validate: func(args []string) (any, gperr.Error) { return validateModField(ModFieldRemove, args) }, build: func(args any) CommandHandler { diff --git a/internal/route/rules/errors.go b/internal/route/rules/errors.go index d30093cf..ec9e86e1 100644 --- a/internal/route/rules/errors.go +++ b/internal/route/rules/errors.go @@ -1,18 +1,20 @@ package rules -import E "github.com/yusing/go-proxy/internal/error" +import ( + "github.com/yusing/go-proxy/internal/gperr" +) var ( - ErrUnterminatedQuotes = E.New("unterminated quotes") - ErrUnsupportedEscapeChar = E.New("unsupported escape char") - ErrUnknownDirective = E.New("unknown directive") - ErrInvalidArguments = E.New("invalid arguments") - ErrInvalidOnTarget = E.New("invalid `rule.on` target") - ErrInvalidCommandSequence = E.New("invalid command sequence") - ErrInvalidSetTarget = E.New("invalid `rule.set` target") + ErrUnterminatedQuotes = gperr.New("unterminated quotes") + ErrUnsupportedEscapeChar = gperr.New("unsupported escape char") + ErrUnknownDirective = gperr.New("unknown directive") + ErrInvalidArguments = gperr.New("invalid arguments") + ErrInvalidOnTarget = gperr.New("invalid `rule.on` target") + ErrInvalidCommandSequence = gperr.New("invalid command sequence") + ErrInvalidSetTarget = gperr.New("invalid `rule.set` target") - ErrExpectNoArg = E.Wrap(ErrInvalidArguments, "expect no arg") - ErrExpectOneArg = E.Wrap(ErrInvalidArguments, "expect 1 arg") - ErrExpectTwoArgs = E.Wrap(ErrInvalidArguments, "expect 2 args") - ErrExpectKVOptionalV = E.Wrap(ErrInvalidArguments, "expect 'key' or 'key value'") + ErrExpectNoArg = gperr.Wrap(ErrInvalidArguments, "expect no arg") + ErrExpectOneArg = gperr.Wrap(ErrInvalidArguments, "expect 1 arg") + ErrExpectTwoArgs = gperr.Wrap(ErrInvalidArguments, "expect 2 args") + ErrExpectKVOptionalV = gperr.Wrap(ErrInvalidArguments, "expect 'key' or 'key value'") ) diff --git a/internal/route/rules/on.go b/internal/route/rules/on.go index e0b18377..8c9e29f7 100644 --- a/internal/route/rules/on.go +++ b/internal/route/rules/on.go @@ -3,7 +3,7 @@ package rules import ( "net/http" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/net/types" "github.com/yusing/go-proxy/internal/utils/strutils" ) @@ -240,7 +240,7 @@ func (on *RuleOn) Parse(v string) error { lines := strutils.SplitLine(v) checkAnd := make(CheckMatchAll, 0, len(lines)) - errs := E.NewBuilder("rule.on syntax errors") + errs := gperr.NewBuilder("rule.on syntax errors") for i, line := range lines { if line == "" { continue @@ -265,11 +265,11 @@ func (on *RuleOn) MarshalText() ([]byte, error) { return []byte(on.String()), nil } -func parseOn(line string) (Checker, E.Error) { +func parseOn(line string) (Checker, gperr.Error) { ors := strutils.SplitRune(line, '|') if len(ors) > 1 { - errs := E.NewBuilder("rule.on syntax errors") + errs := gperr.NewBuilder("rule.on syntax errors") checkOr := make(CheckMatchSingle, len(ors)) for i, or := range ors { curCheckers, err := parseOn(or) diff --git a/internal/route/rules/on_test.go b/internal/route/rules/on_test.go index 7c671cee..fb60ffc2 100644 --- a/internal/route/rules/on_test.go +++ b/internal/route/rules/on_test.go @@ -7,7 +7,7 @@ import ( "net/url" "testing" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" . "github.com/yusing/go-proxy/internal/utils/testing" "golang.org/x/crypto/bcrypt" ) @@ -16,7 +16,7 @@ func TestParseOn(t *testing.T) { tests := []struct { name string input string - wantErr E.Error + wantErr gperr.Error }{ // header { diff --git a/internal/route/rules/parser.go b/internal/route/rules/parser.go index 7ebc689f..dc317b04 100644 --- a/internal/route/rules/parser.go +++ b/internal/route/rules/parser.go @@ -4,7 +4,7 @@ import ( "bytes" "unicode" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" ) var escapedChars = map[rune]rune{ @@ -23,7 +23,7 @@ var escapedChars = map[rune]rune{ // // error 403 "Forbidden 'foo' 'bar'" // error 403 Forbidden\ \"foo\"\ \"bar\". -func parse(v string) (subject string, args []string, err E.Error) { +func parse(v string) (subject string, args []string, err gperr.Error) { buf := bytes.NewBuffer(make([]byte, 0, len(v))) escaped := false diff --git a/internal/route/rules/parser_test.go b/internal/route/rules/parser_test.go index f43f2843..b5743aed 100644 --- a/internal/route/rules/parser_test.go +++ b/internal/route/rules/parser_test.go @@ -4,7 +4,7 @@ import ( "strconv" "testing" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" . "github.com/yusing/go-proxy/internal/utils/testing" ) @@ -14,7 +14,7 @@ func TestParser(t *testing.T) { input string subject string args []string - wantErr E.Error + wantErr gperr.Error }{ { name: "basic", diff --git a/internal/route/rules/validate.go b/internal/route/rules/validate.go index e8943094..58a7dd89 100644 --- a/internal/route/rules/validate.go +++ b/internal/route/rules/validate.go @@ -6,13 +6,13 @@ import ( "path" "strings" - E "github.com/yusing/go-proxy/internal/error" - gphttp "github.com/yusing/go-proxy/internal/net/http" + "github.com/yusing/go-proxy/internal/gperr" + gphttp "github.com/yusing/go-proxy/internal/net/gphttp" "github.com/yusing/go-proxy/internal/net/types" ) type ( - ValidateFunc func(args []string) (any, E.Error) + ValidateFunc func(args []string) (any, gperr.Error) Tuple[T1, T2 any] struct { First T1 Second T2 @@ -29,7 +29,7 @@ func (t *Tuple[T1, T2]) String() string { } // toStrTuple returns *StrTuple. -func toStrTuple(args []string) (any, E.Error) { +func toStrTuple(args []string) (any, gperr.Error) { if len(args) != 2 { return nil, ErrExpectTwoArgs } @@ -37,7 +37,7 @@ func toStrTuple(args []string) (any, E.Error) { } // toKVOptionalV returns *StrTuple that value is optional. -func toKVOptionalV(args []string) (any, E.Error) { +func toKVOptionalV(args []string) (any, gperr.Error) { switch len(args) { case 1: return &StrTuple{args[0], ""}, nil @@ -49,7 +49,7 @@ func toKVOptionalV(args []string) (any, E.Error) { } // validateURL returns types.URL with the URL validated. -func validateURL(args []string) (any, E.Error) { +func validateURL(args []string) (any, gperr.Error) { if len(args) != 1 { return nil, ErrExpectOneArg } @@ -61,7 +61,7 @@ func validateURL(args []string) (any, E.Error) { } // validateAbsoluteURL returns types.URL with the URL validated. -func validateAbsoluteURL(args []string) (any, E.Error) { +func validateAbsoluteURL(args []string) (any, gperr.Error) { if len(args) != 1 { return nil, ErrExpectOneArg } @@ -79,7 +79,7 @@ func validateAbsoluteURL(args []string) (any, E.Error) { } // validateCIDR returns types.CIDR with the CIDR validated. -func validateCIDR(args []string) (any, E.Error) { +func validateCIDR(args []string) (any, gperr.Error) { if len(args) != 1 { return nil, ErrExpectOneArg } @@ -94,7 +94,7 @@ func validateCIDR(args []string) (any, E.Error) { } // validateURLPath returns string with the path validated. -func validateURLPath(args []string) (any, E.Error) { +func validateURLPath(args []string) (any, gperr.Error) { if len(args) != 1 { return nil, ErrExpectOneArg } @@ -112,8 +112,8 @@ func validateURLPath(args []string) (any, E.Error) { } // validateURLPaths returns []string with each element validated. -func validateURLPaths(paths []string) (any, E.Error) { - errs := E.NewBuilder("invalid url paths") +func validateURLPaths(paths []string) (any, gperr.Error) { + errs := gperr.NewBuilder("invalid url paths") for i, p := range paths { val, err := validateURLPath([]string{p}) if err != nil { @@ -129,7 +129,7 @@ func validateURLPaths(paths []string) (any, E.Error) { } // validateFSPath returns string with the path validated. -func validateFSPath(args []string) (any, E.Error) { +func validateFSPath(args []string) (any, gperr.Error) { if len(args) != 1 { return nil, ErrExpectOneArg } @@ -141,7 +141,7 @@ func validateFSPath(args []string) (any, E.Error) { } // validateMethod returns string with the method validated. -func validateMethod(args []string) (any, E.Error) { +func validateMethod(args []string) (any, gperr.Error) { if len(args) != 1 { return nil, ErrExpectOneArg } @@ -153,7 +153,7 @@ func validateMethod(args []string) (any, E.Error) { } // validateUserBCryptPassword returns *HashedCrendential with the password validated. -func validateUserBCryptPassword(args []string) (any, E.Error) { +func validateUserBCryptPassword(args []string) (any, gperr.Error) { if len(args) != 2 { return nil, ErrExpectTwoArgs } @@ -161,7 +161,7 @@ func validateUserBCryptPassword(args []string) (any, E.Error) { } // validateModField returns CommandHandler with the field validated. -func validateModField(mod FieldModifier, args []string) (CommandHandler, E.Error) { +func validateModField(mod FieldModifier, args []string) (CommandHandler, gperr.Error) { setField, ok := modFields[args[0]] if !ok { return nil, ErrInvalidSetTarget.Subject(args[0]) diff --git a/internal/route/stream.go b/internal/route/stream.go index c132aa77..2a6878b8 100755 --- a/internal/route/stream.go +++ b/internal/route/stream.go @@ -30,7 +30,7 @@ type StreamRoute struct { l zerolog.Logger } -func NewStreamRoute(base *Route) (route.Route, E.Error) { +func NewStreamRoute(base *Route) (route.Route, gperr.Error) { // TODO: support non-coherent scheme return &StreamRoute{ Route: base, @@ -46,7 +46,7 @@ func (r *StreamRoute) String() string { } // Start implements task.TaskStarter. -func (r *StreamRoute) Start(parent task.Parent) E.Error { +func (r *StreamRoute) Start(parent task.Parent) gperr.Error { r.task = parent.Subtask("stream." + r.TargetName()) r.Stream = NewStream(r) parent.OnCancel("finish", func() { @@ -78,14 +78,14 @@ func (r *StreamRoute) Start(parent task.Parent) E.Error { if err := r.Stream.Setup(); err != nil { r.task.Finish(err) - return E.From(err) + return gperr.Wrap(err) } r.l.Info().Int("port", r.Port.Listening).Msg("listening") if r.HealthMon != nil { if err := r.HealthMon.Start(r.task); err != nil { - E.LogWarn("health monitor error", err, &r.l) + gperr.LogWarn("health monitor error", err, &r.l) } } @@ -125,7 +125,7 @@ func (r *StreamRoute) acceptConnections() { select { case <-r.task.Context().Done(): default: - E.LogError("accept connection error", err, &r.l) + gperr.LogError("accept connection error", err, &r.l) } r.task.Finish(err) return @@ -136,7 +136,7 @@ func (r *StreamRoute) acceptConnections() { go func() { err := r.Stream.Handle(conn) if err != nil && !errors.Is(err, context.Canceled) { - E.LogError("handle connection error", err, &r.l) + gperr.LogError("handle connection error", err, &r.l) } }() } diff --git a/internal/route/types/port.go b/internal/route/types/port.go index 89ce88fa..57c08fd8 100644 --- a/internal/route/types/port.go +++ b/internal/route/types/port.go @@ -3,7 +3,7 @@ package types import ( "strconv" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/utils/strutils" ) @@ -13,8 +13,8 @@ type Port struct { } var ( - ErrInvalidPortSyntax = E.New("invalid port syntax, expect [listening_port:]target_port") - ErrPortOutOfRange = E.New("port out of range") + ErrInvalidPortSyntax = gperr.New("invalid port syntax, expect [listening_port:]target_port") + ErrPortOutOfRange = gperr.New("port out of range") ) // Parse implements strutils.Parser. @@ -28,7 +28,7 @@ func (p *Port) Parse(v string) (err error) { var err2 error p.Listening, err = strconv.Atoi(parts[0]) p.Proxy, err2 = strconv.Atoi(parts[1]) - err = E.Join(err, err2) + err = gperr.Join(err, err2) default: return ErrInvalidPortSyntax.Subject(v) } diff --git a/internal/route/types/scheme.go b/internal/route/types/scheme.go index 6830c6ef..cbb4ce29 100644 --- a/internal/route/types/scheme.go +++ b/internal/route/types/scheme.go @@ -1,12 +1,12 @@ package types import ( - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" ) type Scheme string -var ErrInvalidScheme = E.New("invalid scheme") +var ErrInvalidScheme = gperr.New("invalid scheme") const ( SchemeHTTP Scheme = "http" @@ -16,7 +16,7 @@ const ( SchemeFileServer Scheme = "fileserver" ) -func (s Scheme) Validate() E.Error { +func (s Scheme) Validate() gperr.Error { switch s { case SchemeHTTP, SchemeHTTPS, SchemeTCP, SchemeUDP, SchemeFileServer: diff --git a/internal/route/udp_forwarder.go b/internal/route/udp_forwarder.go index d33b91bf..62149afa 100644 --- a/internal/route/udp_forwarder.go +++ b/internal/route/udp_forwarder.go @@ -6,7 +6,7 @@ import ( "net" "sync" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/logging" "github.com/yusing/go-proxy/internal/net/types" F "github.com/yusing/go-proxy/internal/utils/functional" @@ -192,7 +192,7 @@ func (w *UDPForwarder) Handle(streamConn types.StreamConn) error { } func (w *UDPForwarder) Close() error { - errs := E.NewBuilder("errors closing udp conn") + errs := gperr.NewBuilder("errors closing udp conn") w.mu.Lock() defer w.mu.Unlock() w.connMap.RangeAll(func(key string, conn *UDPConn) { diff --git a/internal/task/task.go b/internal/task/task.go index 19a5f8a3..2421a136 100644 --- a/internal/task/task.go +++ b/internal/task/task.go @@ -8,7 +8,7 @@ import ( "time" "github.com/yusing/go-proxy/internal/common" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/logging" "github.com/yusing/go-proxy/internal/utils/strutils" ) @@ -19,7 +19,7 @@ type ( // and returns an error if it fails to start. // // callerSubtask.Finish must be called when start fails or the object is finished. - Start(parent Parent) E.Error + Start(parent Parent) gperr.Error Task() *Task } TaskFinisher interface { diff --git a/internal/utils/io.go b/internal/utils/io.go index 0e65c464..1cae52f6 100644 --- a/internal/utils/io.go +++ b/internal/utils/io.go @@ -7,7 +7,7 @@ import ( "sync" "syscall" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" ) // TODO: move to "utils/io". @@ -81,10 +81,10 @@ func NewBidirectionalPipe(ctx context.Context, rw1 io.ReadWriteCloser, rw2 io.Re } } -func (p BidirectionalPipe) Start() E.Error { +func (p BidirectionalPipe) Start() gperr.Error { var wg sync.WaitGroup wg.Add(2) - b := E.NewBuilder("bidirectional pipe error") + b := gperr.NewBuilder("bidirectional pipe error") go func() { b.Add(p.pSrcDst.Start()) wg.Done() diff --git a/internal/utils/serialization.go b/internal/utils/serialization.go index 6830efd8..0cc4f987 100644 --- a/internal/utils/serialization.go +++ b/internal/utils/serialization.go @@ -11,7 +11,7 @@ import ( "time" "github.com/go-playground/validator/v10" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/utils/functional" "github.com/yusing/go-proxy/internal/utils/strutils" "gopkg.in/yaml.v3" @@ -20,15 +20,15 @@ import ( type SerializedObject = map[string]any type MapUnmarshaller interface { - UnmarshalMap(m map[string]any) E.Error + UnmarshalMap(m map[string]any) gperr.Error } var ( - ErrInvalidType = E.New("invalid type") - ErrNilValue = E.New("nil") - ErrUnsettable = E.New("unsettable") - ErrUnsupportedConversion = E.New("unsupported conversion") - ErrUnknownField = E.New("unknown field") + ErrInvalidType = gperr.New("invalid type") + ErrNilValue = gperr.New("nil") + ErrUnsettable = gperr.New("unsettable") + ErrUnsupportedConversion = gperr.New("unsupported conversion") + ErrUnknownField = gperr.New("unknown field") ) var ( @@ -89,8 +89,8 @@ func extractFields(t reflect.Type) (all, anonymous []reflect.StructField) { return fields, anonymous } -func ValidateWithFieldTags(s any) E.Error { - errs := E.NewBuilder("validate error") +func ValidateWithFieldTags(s any) gperr.Error { + errs := gperr.NewBuilder("validate error") err := validate.Struct(s) var valErrs validator.ValidationErrors if errors.As(err, &valErrs) { @@ -107,13 +107,13 @@ func ValidateWithFieldTags(s any) E.Error { return errs.Error() } -func ValidateWithCustomValidator(v reflect.Value) E.Error { +func ValidateWithCustomValidator(v reflect.Value) gperr.Error { isStruct := false for { switch v.Kind() { case reflect.Pointer, reflect.Interface: if v.IsNil() { - return E.Errorf("validate: v is %w", ErrNilValue) + return gperr.Errorf("validate: v is %w", ErrNilValue) } if validate, ok := v.Interface().(CustomValidator); ok { return validate.Validate() @@ -134,14 +134,14 @@ func ValidateWithCustomValidator(v reflect.Value) E.Error { } } -func dive(dst reflect.Value) (v reflect.Value, t reflect.Type, err E.Error) { +func dive(dst reflect.Value) (v reflect.Value, t reflect.Type, err gperr.Error) { dstT := dst.Type() for { switch dst.Kind() { case reflect.Pointer, reflect.Interface: if dst.IsNil() { if !dst.CanSet() { - err = E.Errorf("dive: dst is %w and is not settable", ErrNilValue) + err = gperr.Errorf("dive: dst is %w and is not settable", ErrNilValue) return } dst.Set(New(dstT.Elem())) @@ -158,7 +158,7 @@ func dive(dst reflect.Value) (v reflect.Value, t reflect.Type, err E.Error) { case reflect.Slice: dst.Set(reflect.MakeSlice(dstT, 0, 0)) default: - err = E.Errorf("deserialize: %w for dst %s", ErrInvalidType, dstT.String()) + err = gperr.Errorf("deserialize: %w for dst %s", ErrInvalidType, dstT.String()) return } } @@ -180,7 +180,7 @@ func dive(dst reflect.Value) (v reflect.Value, t reflect.Type, err E.Error) { // If the target value is a map[string]any the SerializedObject will be deserialized into the map. // // The function returns an error if the target value is not a struct or a map[string]any, or if there is an error during deserialization. -func Deserialize(src SerializedObject, dst any) (err E.Error) { +func Deserialize(src SerializedObject, dst any) (err gperr.Error) { dstV := reflect.ValueOf(dst) dstT := dstV.Type() @@ -189,7 +189,7 @@ func Deserialize(src SerializedObject, dst any) (err E.Error) { dstV.Set(reflect.Zero(dstT)) return nil } - return E.Errorf("deserialize: src is %w and dst is not settable\n%s", ErrNilValue, debug.Stack()) + return gperr.Errorf("deserialize: src is %w and dst is not settable\n%s", ErrNilValue, debug.Stack()) } if dstT.Implements(mapUnmarshalerType) { @@ -209,7 +209,7 @@ func Deserialize(src SerializedObject, dst any) (err E.Error) { // convert target fields to lower no-snake // then check if the field of data is in the target - errs := E.NewBuilder("deserialize error") + errs := gperr.NewBuilder("deserialize error") switch dstV.Kind() { case reflect.Struct, reflect.Interface: @@ -302,9 +302,9 @@ func isIntFloat(t reflect.Kind) bool { // // Returns: // - error: the error occurred during conversion, or nil if no error occurred. -func Convert(src reflect.Value, dst reflect.Value) E.Error { +func Convert(src reflect.Value, dst reflect.Value) gperr.Error { if !dst.IsValid() { - return E.Errorf("convert: dst is %w", ErrNilValue) + return gperr.Errorf("convert: dst is %w", ErrNilValue) } if !src.IsValid() { @@ -312,7 +312,7 @@ func Convert(src reflect.Value, dst reflect.Value) E.Error { dst.Set(reflect.Zero(dst.Type())) return nil } - return E.Errorf("convert: src is %w", ErrNilValue) + return gperr.Errorf("convert: src is %w", ErrNilValue) } srcT := src.Type() @@ -379,7 +379,7 @@ func Convert(src reflect.Value, dst reflect.Value) E.Error { if dstT.Kind() != reflect.Slice { return ErrUnsupportedConversion.Subject(dstT.String() + " to " + srcT.String()) } - sliceErrs := E.NewBuilder("slice conversion errors") + sliceErrs := gperr.NewBuilder("slice conversion errors") newSlice := reflect.MakeSlice(dstT, src.Len(), src.Len()) i := 0 for j, v := range src.Seq2() { @@ -401,7 +401,7 @@ func Convert(src reflect.Value, dst reflect.Value) E.Error { return ErrUnsupportedConversion.Subjectf("%s to %s", srcT, dstT) } -func ConvertString(src string, dst reflect.Value) (convertible bool, convErr E.Error) { +func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gperr.Error) { convertible = true dstT := dst.Type() if dst.Kind() == reflect.Ptr { @@ -423,7 +423,7 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr E.E } d, err := time.ParseDuration(src) if err != nil { - return true, E.From(err) + return true, gperr.Wrap(err) } dst.Set(reflect.ValueOf(d)) return @@ -443,14 +443,14 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr E.E i, err = strconv.ParseFloat(src, dstT.Bits()) } if err != nil { - return true, E.From(err) + return true, gperr.Wrap(err) } dst.Set(reflect.ValueOf(i).Convert(dstT)) return } // check if (*T).Convertor is implemented if parser, ok := dst.Addr().Interface().(strutils.Parser); ok { - return true, E.From(parser.Parse(src)) + return true, gperr.Wrap(parser.Parse(src)) } // yaml like var tmp any @@ -462,7 +462,7 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr E.E if !isMultiline && src[0] != '-' { values := strutils.CommaSeperatedList(src) dst.Set(reflect.MakeSlice(dst.Type(), len(values), len(values))) - errs := E.NewBuilder("invalid slice values") + errs := gperr.NewBuilder("invalid slice values") for i, v := range values { err := Convert(reflect.ValueOf(v), dst.Index(i)) if err != nil { @@ -477,14 +477,14 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr E.E sl := make([]any, 0) err := yaml.Unmarshal([]byte(src), &sl) if err != nil { - return true, E.From(err) + return true, gperr.Wrap(err) } tmp = sl case reflect.Map, reflect.Struct: rawMap := make(SerializedObject) err := yaml.Unmarshal([]byte(src), &rawMap) if err != nil { - return true, E.From(err) + return true, gperr.Wrap(err) } tmp = rawMap default: @@ -493,17 +493,17 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr E.E return true, Convert(reflect.ValueOf(tmp), dst) } -func DeserializeYAML[T any](data []byte, target *T) E.Error { +func DeserializeYAML[T any](data []byte, target *T) gperr.Error { m := make(map[string]any) if err := yaml.Unmarshal(data, m); err != nil { - return E.From(err) + return gperr.Wrap(err) } return Deserialize(m, target) } -func DeserializeYAMLMap[V any](data []byte) (_ functional.Map[string, V], err E.Error) { +func DeserializeYAMLMap[V any](data []byte) (_ functional.Map[string, V], err gperr.Error) { m := make(map[string]any) - if err = E.From(yaml.Unmarshal(data, m)); err != nil { + if err = gperr.Wrap(yaml.Unmarshal(data, m)); err != nil { return } m2 := make(map[string]V, len(m)) diff --git a/internal/utils/validation.go b/internal/utils/validation.go index 32db1242..490c348e 100644 --- a/internal/utils/validation.go +++ b/internal/utils/validation.go @@ -2,15 +2,15 @@ package utils import ( "github.com/go-playground/validator/v10" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" ) var validate = validator.New() -var ErrValidationError = E.New("validation error") +var ErrValidationError = gperr.New("validation error") type CustomValidator interface { - Validate() E.Error + Validate() gperr.Error } func Validator() *validator.Validate { diff --git a/internal/watcher/directory_watcher.go b/internal/watcher/directory_watcher.go index 171d59ed..45cca6a3 100644 --- a/internal/watcher/directory_watcher.go +++ b/internal/watcher/directory_watcher.go @@ -8,7 +8,7 @@ import ( "github.com/fsnotify/fsnotify" "github.com/rs/zerolog" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/logging" "github.com/yusing/go-proxy/internal/task" "github.com/yusing/go-proxy/internal/watcher/events" @@ -24,7 +24,7 @@ type DirWatcher struct { mu sync.Mutex eventCh chan Event - errCh chan E.Error + errCh chan gperr.Error task *task.Task } @@ -55,14 +55,14 @@ func NewDirectoryWatcher(parent task.Parent, dirPath string) *DirWatcher { w: w, fwMap: make(map[string]*fileWatcher), eventCh: make(chan Event), - errCh: make(chan E.Error), + errCh: make(chan gperr.Error), task: parent.Subtask("dir_watcher(" + dirPath + ")"), } go helper.start() return helper } -func (h *DirWatcher) Events(_ context.Context) (<-chan Event, <-chan E.Error) { +func (h *DirWatcher) Events(_ context.Context) (<-chan Event, <-chan gperr.Error) { return h.eventCh, h.errCh } @@ -78,7 +78,7 @@ func (h *DirWatcher) Add(relPath string) Watcher { s = &fileWatcher{ relPath: relPath, eventCh: make(chan Event), - errCh: make(chan E.Error), + errCh: make(chan gperr.Error), } h.fwMap[relPath] = s return s @@ -162,7 +162,7 @@ func (h *DirWatcher) start() { return } select { - case h.errCh <- E.From(err): + case h.errCh <- gperr.Wrap(err): default: } } diff --git a/internal/watcher/docker_watcher.go b/internal/watcher/docker_watcher.go index 4cac0d81..ae6b6532 100644 --- a/internal/watcher/docker_watcher.go +++ b/internal/watcher/docker_watcher.go @@ -7,7 +7,7 @@ import ( docker_events "github.com/docker/docker/api/types/events" "github.com/docker/docker/api/types/filters" "github.com/yusing/go-proxy/internal/docker" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/watcher/events" ) @@ -51,13 +51,13 @@ func NewDockerWatcher(host string) DockerWatcher { return DockerWatcher{host: host} } -func (w DockerWatcher) Events(ctx context.Context) (<-chan Event, <-chan E.Error) { +func (w *DockerWatcher) Events(ctx context.Context) (<-chan Event, <-chan gperr.Error) { return w.EventsWithOptions(ctx, optionsDefault) } -func (w DockerWatcher) EventsWithOptions(ctx context.Context, options DockerListOptions) (<-chan Event, <-chan E.Error) { +func (w *DockerWatcher) EventsWithOptions(ctx context.Context, options DockerListOptions) (<-chan Event, <-chan gperr.Error) { eventCh := make(chan Event) - errCh := make(chan E.Error) + errCh := make(chan gperr.Error) go func() { defer func() { diff --git a/internal/watcher/events/event_queue.go b/internal/watcher/events/event_queue.go index 563c8cd5..276a2d9e 100644 --- a/internal/watcher/events/event_queue.go +++ b/internal/watcher/events/event_queue.go @@ -5,7 +5,7 @@ import ( "time" "github.com/yusing/go-proxy/internal/common" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/task" ) @@ -19,7 +19,7 @@ type ( onError OnErrorFunc } OnFlushFunc = func(events []Event) - OnErrorFunc = func(err E.Error) + OnErrorFunc = func(err gperr.Error) ) const eventQueueCapacity = 10 @@ -50,13 +50,13 @@ func NewEventQueue(queueTask *task.Task, flushInterval time.Duration, onFlush On } } -func (e *EventQueue) Start(eventCh <-chan Event, errCh <-chan E.Error) { +func (e *EventQueue) Start(eventCh <-chan Event, errCh <-chan gperr.Error) { origOnFlush := e.onFlush // recover panic in onFlush when in production mode e.onFlush = func(events []Event) { defer func() { if err := recover(); err != nil { - e.onError(E.New("recovered panic in onFlush"). + e.onError(gperr.New("recovered panic in onFlush"). Withf("%v", err). Subject(e.task.Name())) if common.IsDebug { diff --git a/internal/watcher/file_watcher.go b/internal/watcher/file_watcher.go index a53025d9..41989a15 100644 --- a/internal/watcher/file_watcher.go +++ b/internal/watcher/file_watcher.go @@ -3,15 +3,15 @@ package watcher import ( "context" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" ) type fileWatcher struct { relPath string eventCh chan Event - errCh chan E.Error + errCh chan gperr.Error } -func (fw *fileWatcher) Events(ctx context.Context) (<-chan Event, <-chan E.Error) { +func (fw *fileWatcher) Events(ctx context.Context) (<-chan Event, <-chan gperr.Error) { return fw.eventCh, fw.errCh } diff --git a/internal/watcher/health/monitor/monitor.go b/internal/watcher/health/monitor/monitor.go index 32a2fd0c..4349b703 100644 --- a/internal/watcher/health/monitor/monitor.go +++ b/internal/watcher/health/monitor/monitor.go @@ -58,13 +58,9 @@ func (mon *monitor) ContextWithTimeout(cause string) (ctx context.Context, cance } // Start implements task.TaskStarter. -func (mon *monitor) Start(parent task.Parent) E.Error { +func (mon *monitor) Start(parent task.Parent) gperr.Error { if mon.config.Interval <= 0 { - return E.From(ErrNegativeInterval) - } - - if common.PrometheusEnabled { - mon.metric = metrics.GetServiceMetrics().HealthStatus.With(metrics.HealthMetricLabels(mon.service)) + return gperr.Wrap(ErrNegativeInterval) } mon.service = parent.Name() diff --git a/internal/watcher/watcher.go b/internal/watcher/watcher.go index e33cd551..1c51ec8b 100644 --- a/internal/watcher/watcher.go +++ b/internal/watcher/watcher.go @@ -3,12 +3,12 @@ package watcher import ( "context" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/watcher/events" ) type Event = events.Event type Watcher interface { - Events(ctx context.Context) (<-chan Event, <-chan E.Error) + Events(ctx context.Context) (<-chan Event, <-chan gperr.Error) }