diff --git a/Dockerfile b/Dockerfile index a16be06..ac7dc06 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,9 @@ # Stage 1: Builder FROM golang:1.23.3-alpine AS builder +HEALTHCHECK NONE + +# package version does not matter +# trunk-ignore(hadolint/DL3018) RUN apk add --no-cache tzdata make WORKDIR /src @@ -58,4 +62,4 @@ EXPOSE 443 WORKDIR /app -CMD ["/app/godoxy"] +CMD ["/app/godoxy"] \ No newline at end of file diff --git a/cmd/main.go b/cmd/main.go index 30fbab1..872b024 100755 --- a/cmd/main.go +++ b/cmd/main.go @@ -160,7 +160,7 @@ func main() { // grafully shutdown logging.Info().Msg("shutting down") task.CancelGlobalContext() - task.GlobalContextWait(time.Second * time.Duration(config.Value().TimeoutShutdown)) + _ = task.GlobalContextWait(time.Second * time.Duration(config.Value().TimeoutShutdown)) } func prepareDirectory(dir string) { diff --git a/internal/docker/idlewatcher/watcher.go b/internal/docker/idlewatcher/watcher.go index f578029..f8e9f2a 100644 --- a/internal/docker/idlewatcher/watcher.go +++ b/internal/docker/idlewatcher/watcher.go @@ -44,6 +44,8 @@ var ( watcherMap = F.NewMapOf[string, *Watcher]() watcherMapMu sync.Mutex + errShouldNotReachHere = errors.New("should not reach here") + logger = logging.With().Str("module", "idle_watcher").Logger() ) @@ -53,7 +55,7 @@ func registerWatcher(providerSubtask task.Task, entry route.Entry, waker *waker) cfg := entry.IdlewatcherConfig() if cfg.IdleTimeout == 0 { - panic("should not reach here") + panic(errShouldNotReachHere) } watcherMapMu.Lock() @@ -104,10 +106,12 @@ func (w *Watcher) Wake() error { // WakeDebug logs a debug message related to waking the container. func (w *Watcher) WakeDebug() *zerolog.Event { + //nolint:zerologlint return w.Debug().Str("action", "wake") } func (w *Watcher) WakeTrace() *zerolog.Event { + //nolint:zerologlint return w.Trace().Str("action", "wake") } @@ -177,7 +181,7 @@ func (w *Watcher) wakeIfStopped() error { case "running": return nil default: - panic("should not reach here") + panic(errShouldNotReachHere) } } @@ -191,7 +195,7 @@ func (w *Watcher) getStopCallback() StopCallback { case idlewatcher.StopMethodKill: cb = w.containerKill default: - panic("should not reach here") + panic(errShouldNotReachHere) } return func() error { ctx, cancel := context.WithTimeout(w.task.Context(), time.Duration(w.StopTimeout)*time.Second) diff --git a/internal/error/base.go b/internal/error/base.go index d1287ab..fea4382 100644 --- a/internal/error/base.go +++ b/internal/error/base.go @@ -1,4 +1,4 @@ -package error +package err import ( "errors" @@ -6,6 +6,8 @@ import ( ) // baseError is an immutable wrapper around an error. +// +//nolint:recvcheck type baseError struct { Err error `json:"err"` } diff --git a/internal/error/builder.go b/internal/error/builder.go index 80681c1..96fb886 100644 --- a/internal/error/builder.go +++ b/internal/error/builder.go @@ -1,4 +1,4 @@ -package error +package err import ( "fmt" @@ -60,7 +60,7 @@ func (b *Builder) Add(err error) *Builder { b.Lock() defer b.Unlock() - switch err := err.(type) { + switch err := From(err).(type) { case *baseError: b.errs = append(b.errs, err.Err) case *nestedError: @@ -70,7 +70,7 @@ func (b *Builder) Add(err error) *Builder { b.errs = append(b.errs, err) } default: - b.errs = append(b.errs, err) + panic("bug: should not reach here") } return b diff --git a/internal/error/builder_test.go b/internal/error/builder_test.go index ec22615..2975e4a 100644 --- a/internal/error/builder_test.go +++ b/internal/error/builder_test.go @@ -1,4 +1,4 @@ -package error_test +package err_test import ( "context" diff --git a/internal/error/error.go b/internal/error/error.go index 5e744ba..03e0079 100644 --- a/internal/error/error.go +++ b/internal/error/error.go @@ -1,4 +1,4 @@ -package error +package err type Error interface { error @@ -24,6 +24,8 @@ type Error interface { // this makes JSON marshaling work, // as the builtin one doesn't. +// +//nolint:errname type errStr string func (err errStr) Error() string { diff --git a/internal/error/error_test.go b/internal/error/error_test.go index 0ac2902..6966760 100644 --- a/internal/error/error_test.go +++ b/internal/error/error_test.go @@ -1,4 +1,4 @@ -package error +package err import ( "errors" @@ -81,10 +81,10 @@ func TestErrorImmutability(t *testing.T) { for range 3 { // t.Logf("%d: %v %T %s", i, errors.Unwrap(err), err, err) - err.Subject("foo") + _ = err.Subject("foo") ExpectFalse(t, strings.Contains(err.Error(), "foo")) - err.With(err2) + _ = err.With(err2) ExpectFalse(t, strings.Contains(err.Error(), "extra")) ExpectFalse(t, err.Is(err2)) @@ -102,7 +102,7 @@ func TestErrorWith(t *testing.T) { ExpectTrue(t, err3.Is(err1)) ExpectTrue(t, err3.Is(err2)) - err2.Subject("foo") + _ = err2.Subject("foo") ExpectTrue(t, err3.Is(err1)) ExpectTrue(t, err3.Is(err2)) diff --git a/internal/error/log.go b/internal/error/log.go index 56990a8..7e79d1e 100644 --- a/internal/error/log.go +++ b/internal/error/log.go @@ -1,4 +1,4 @@ -package error +package err import ( "github.com/rs/zerolog" diff --git a/internal/error/nested_error.go b/internal/error/nested_error.go index a2fdc61..acff977 100644 --- a/internal/error/nested_error.go +++ b/internal/error/nested_error.go @@ -1,4 +1,4 @@ -package error +package err import ( "errors" @@ -6,6 +6,7 @@ import ( "strings" ) +//nolint:recvcheck type nestedError struct { Err error `json:"err"` Extras []error `json:"extras"` @@ -66,7 +67,18 @@ func (err *nestedError) Is(other error) bool { } func (err *nestedError) Error() string { - return buildError(err, 0) + if err == nil { + return makeLine("", 0) + } + + lines := make([]string, 0, 1+len(err.Extras)) + if err.Err != nil { + lines = append(lines, makeLine(err.Err.Error(), 0)) + } + if extras := makeLines(err.Extras, 1); len(extras) > 0 { + lines = append(lines, extras...) + } + return strings.Join(lines, "\n") } //go:inline @@ -86,7 +98,7 @@ func makeLines(errs []error, level int) []string { } lines := make([]string, 0, len(errs)) for _, err := range errs { - switch err := err.(type) { + switch err := From(err).(type) { case *nestedError: if err.Err != nil { lines = append(lines, makeLine(err.Err.Error(), level)) @@ -100,21 +112,3 @@ func makeLines(errs []error, level int) []string { } return lines } - -func buildError(err error, level int) string { - switch err := err.(type) { - case nil: - return makeLine("", level) - case *nestedError: - lines := make([]string, 0, 1+len(err.Extras)) - if err.Err != nil { - lines = append(lines, makeLine(err.Err.Error(), level)) - } - if extras := makeLines(err.Extras, level+1); len(extras) > 0 { - lines = append(lines, extras...) - } - return strings.Join(lines, "\n") - default: - return makeLine(err.Error(), level) - } -} diff --git a/internal/error/subject.go b/internal/error/subject.go index e146139..b649f0e 100644 --- a/internal/error/subject.go +++ b/internal/error/subject.go @@ -1,4 +1,4 @@ -package error +package err import ( "strings" @@ -6,6 +6,7 @@ import ( "github.com/yusing/go-proxy/internal/utils/strutils/ansi" ) +//nolint:errname type withSubject struct { Subject string `json:"subject"` Err error `json:"err"` @@ -18,23 +19,26 @@ func highlight(subject string) string { } func PrependSubject(subject string, err error) error { - switch err := err.(type) { - case nil: + if err == nil { return nil + } + + //nolint:errorlint + switch err := err.(type) { case *withSubject: return err.Prepend(subject) case Error: return err.Subject(subject) - default: - return &withSubject{subject, err} } + return &withSubject{subject, err} } -func (err withSubject) Prepend(subject string) *withSubject { +func (err *withSubject) Prepend(subject string) *withSubject { + clone := *err if subject != "" { - err.Subject = subject + subjectSep + err.Subject + clone.Subject = subject + subjectSep + clone.Subject } - return &err + return &clone } func (err *withSubject) Is(other error) bool { diff --git a/internal/error/utils.go b/internal/error/utils.go index eeda0c9..4af9300 100644 --- a/internal/error/utils.go +++ b/internal/error/utils.go @@ -1,6 +1,7 @@ -package error +package err import ( + "errors" "fmt" ) @@ -19,12 +20,12 @@ func Errorf(format string, args ...any) Error { return &baseError{fmt.Errorf(format, args...)} } -func From(err error) Error { +func From(err error) (e Error) { if err == nil { return nil } - if err, ok := err.(Error); ok { - return err + if errors.As(err, &e) { + return e } return &baseError{err} } diff --git a/internal/homepage/homepage.go b/internal/homepage/homepage.go index 2dba64c..03ccf6f 100644 --- a/internal/homepage/homepage.go +++ b/internal/homepage/homepage.go @@ -1,6 +1,7 @@ package homepage type ( + //nolint:recvcheck Config map[string]Category Category []*Item diff --git a/internal/logging/logging.go b/internal/logging/logging.go index 015a50f..69c5136 100644 --- a/internal/logging/logging.go +++ b/internal/logging/logging.go @@ -1,3 +1,4 @@ +//nolint:zerologlint package logging import ( diff --git a/internal/net/http/middleware/real_ip.go b/internal/net/http/middleware/real_ip.go index da3f3e0..df16cfb 100644 --- a/internal/net/http/middleware/real_ip.go +++ b/internal/net/http/middleware/real_ip.go @@ -81,8 +81,8 @@ func (ri *realIP) setRealIP(req *http.Request) { return } - var realIPs = req.Header.Values(ri.Header) - var lastNonTrustedIP string + realIPs := req.Header.Values(ri.Header) + lastNonTrustedIP := "" if len(realIPs) == 0 { ri.AddTracef("no real ip found in header %s", ri.Header).WithRequest(req) diff --git a/internal/notif/providers.go b/internal/notif/providers.go index c09c6d1..bb6aa5b 100644 --- a/internal/notif/providers.go +++ b/internal/notif/providers.go @@ -45,10 +45,14 @@ func newNotifProvider[T Provider](cfg map[string]any) (Provider, E.Error) { return client, nil } +func formatError(p Provider, err error) error { + return fmt.Errorf("%s error: %w", p.Name(), err) +} + func notifyProvider(ctx context.Context, provider Provider, msg *LogMessage) error { body, err := provider.MakeBody(msg) if err != nil { - return fmt.Errorf("%s error: %w", provider.Name(), err) + return formatError(provider, err) } req, err := http.NewRequestWithContext( ctx, @@ -57,7 +61,7 @@ func notifyProvider(ctx context.Context, provider Provider, msg *LogMessage) err body, ) if err != nil { - return fmt.Errorf("%s error: %w", provider.Name(), err) + return formatError(provider, err) } req.Header.Set("Content-Type", provider.MIMEType()) @@ -67,7 +71,7 @@ func notifyProvider(ctx context.Context, provider Provider, msg *LogMessage) err resp, err := http.DefaultClient.Do(req) if err != nil { - return fmt.Errorf("%s error: %w", provider.Name(), err) + return formatError(provider, err) } defer resp.Body.Close() diff --git a/internal/route/http.go b/internal/route/http.go index e74d78f..ac903d1 100755 --- a/internal/route/http.go +++ b/internal/route/http.go @@ -174,7 +174,9 @@ func (r *HTTPRoute) addToLoadBalancer() { lbTask.OnCancel("remove lb from routes", func() { routes.DeleteHTTPRoute(r.LoadBalance.Link) }) - lb.Start(lbTask) + if err := lb.Start(lbTask); err != nil { + panic(err) // should always return nil + } linked = &HTTPRoute{ ReverseProxyEntry: &entry.ReverseProxyEntry{ Raw: &route.RawEntry{ diff --git a/internal/route/types/raw_entry.go b/internal/route/types/raw_entry.go index 9a1e2d3..e9e0168 100644 --- a/internal/route/types/raw_entry.go +++ b/internal/route/types/raw_entry.go @@ -1,3 +1,4 @@ +//nolint:goconst package types import ( diff --git a/internal/route/udp_forwarder.go b/internal/route/udp_forwarder.go index 8ed4532..afb4c3e 100644 --- a/internal/route/udp_forwarder.go +++ b/internal/route/udp_forwarder.go @@ -96,16 +96,16 @@ func (w *UDPForwarder) readFromListener(buf *UDPBuf) (srcAddr *net.UDPAddr, err return } -func (dst *UDPConn) read() (err error) { - switch dstConn := dst.conn.(type) { +func (conn *UDPConn) read() (err error) { + switch dstConn := conn.conn.(type) { case *net.UDPConn: - dst.buf.n, dst.buf.oobn, _, _, err = dstConn.ReadMsgUDP(dst.buf.data, dst.buf.oob) + conn.buf.n, conn.buf.oobn, _, _, err = dstConn.ReadMsgUDP(conn.buf.data, conn.buf.oob) default: - dst.buf.n, err = dstConn.Read(dst.buf.data[:dst.buf.n]) - dst.buf.oobn = 0 + conn.buf.n, err = dstConn.Read(conn.buf.data[:conn.buf.n]) + conn.buf.oobn = 0 } if err == nil { - logger.Debug().Msgf("read from dst %s success (n: %d, oobn: %d)", dst.DstAddrString(), dst.buf.n, dst.buf.oobn) + logger.Debug().Msgf("read from dst %s success (n: %d, oobn: %d)", conn.DstAddrString(), conn.buf.n, conn.buf.oobn) } return } @@ -118,17 +118,17 @@ func (w *UDPForwarder) writeToSrc(srcAddr *net.UDPAddr, buf *UDPBuf) (err error) return } -func (dst *UDPConn) write() (err error) { - switch dstConn := dst.conn.(type) { +func (conn *UDPConn) write() (err error) { + switch dstConn := conn.conn.(type) { case *net.UDPConn: - dst.buf.n, dst.buf.oobn, err = dstConn.WriteMsgUDP(dst.buf.data[:dst.buf.n], dst.buf.oob[:dst.buf.oobn], nil) + conn.buf.n, conn.buf.oobn, err = dstConn.WriteMsgUDP(conn.buf.data[:conn.buf.n], conn.buf.oob[:conn.buf.oobn], nil) if err == nil { - logger.Debug().Msgf("write to dst %s success (n: %d, oobn: %d)", dst.DstAddrString(), dst.buf.n, dst.buf.oobn) + logger.Debug().Msgf("write to dst %s success (n: %d, oobn: %d)", conn.DstAddrString(), conn.buf.n, conn.buf.oobn) } default: - _, err = dstConn.Write(dst.buf.data[:dst.buf.n]) + _, err = dstConn.Write(conn.buf.data[:conn.buf.n]) if err == nil { - logger.Debug().Msgf("write to dst %s success (n: %d)", dst.DstAddrString(), dst.buf.n) + logger.Debug().Msgf("write to dst %s success (n: %d)", conn.DstAddrString(), conn.buf.n) } } diff --git a/internal/utils/serialization.go b/internal/utils/serialization.go index 6d17129..80bf006 100644 --- a/internal/utils/serialization.go +++ b/internal/utils/serialization.go @@ -149,7 +149,7 @@ func extractFields(t reflect.Type) []reflect.StructField { return nil } var fields []reflect.StructField - for i := 0; i < t.NumField(); i++ { + for i := range t.NumField() { field := t.Field(i) if !field.IsExported() { continue diff --git a/internal/utils/strutils/string.go b/internal/utils/strutils/string.go index c329f2f..f420e71 100644 --- a/internal/utils/strutils/string.go +++ b/internal/utils/strutils/string.go @@ -32,6 +32,7 @@ func ToLowerNoSnake(s string) string { return strings.ToLower(strings.ReplaceAll(s, "_", "")) } +//nolint:intrange func LevenshteinDistance(a, b string) int { if a == b { return 0 diff --git a/internal/watcher/health/monitor/raw.go b/internal/watcher/health/monitor/raw.go index 66d9296..af3381c 100644 --- a/internal/watcher/health/monitor/raw.go +++ b/internal/watcher/health/monitor/raw.go @@ -41,7 +41,6 @@ func (mon *RawHealthMonitor) CheckHealth() (result *health.HealthCheckResult, er } if dialErr != nil { result.Detail = dialErr.Error() - /* trunk-ignore(golangci-lint/nilerr) */ return } conn.Close()