diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 21038c31..7daf2cc6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,9 +32,14 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v6 with: - version: latest - env: - TZ: "America/Chicago" + version: v1.58 + + - name: golangci-lint on example directory + uses: golangci/golangci-lint-action@v6 + with: + version: v1.58 + args: --config ../../.golangci.yml + working-directory: examples/plugin - name: install goveralls run: | diff --git a/.golangci.yml b/.golangci.yml index 13b39330..758c4985 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,17 +1,10 @@ run: timeout: 5m - output: - format: tab - skip-dirs: - - vendor linters-settings: govet: - check-shadowing: true - golint: - min-confidence: 0.1 - maligned: - suggest-new: true + enable: + - shadow goconst: min-len: 2 min-occurrences: 2 @@ -33,13 +26,12 @@ linters-settings: linters: enable: - - megacheck + - staticcheck - revive - govet - unconvert - - megacheck - unused - - gas + - gosec - gocyclo - dupl - misspell @@ -57,6 +49,8 @@ linters: disable-all: true issues: + exclude-dirs: + - vendor exclude-rules: - text: "at least one file in a package should have a package comment" linters: diff --git a/examples/plugin/go.sum b/examples/plugin/go.sum index 91febb9d..789326a2 100644 --- a/examples/plugin/go.sum +++ b/examples/plugin/go.sum @@ -9,7 +9,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/plugin/main.go b/examples/plugin/main.go index feec46a8..57797c34 100644 --- a/examples/plugin/main.go +++ b/examples/plugin/main.go @@ -9,7 +9,6 @@ import ( ) func main() { - // create demo plugin on port 1234 with two methods: HeaderThing and ErrorThing // both called via RPC from reproxy core with fully formed lib.Request plugin := lib.Plugin{ @@ -18,16 +17,17 @@ func main() { Methods: []string{"HeaderThing", "ErrorThing"}, } log.Printf("start demo plugin") - // Do starts the plugin listener and register with reproxy plugin conductor + // Do start the plugin listener and register with reproxy plugin conductor if err := plugin.Do(context.TODO(), "http://reproxy:8081", new(Handler)); err != nil { log.Fatal(err) } } -// Handler is an example of middleware handler altering headers and stastus +// Handler is an example of middleware handler altering headers and status type Handler struct{} // HeaderThing adds key:val header to the response +// nolint:unparam // error response is required by the interface func (h *Handler) HeaderThing(req lib.Request, res *lib.Response) (err error) { log.Printf("req: %+v", req) res.HeadersOut = http.Header{} @@ -39,6 +39,7 @@ func (h *Handler) HeaderThing(req lib.Request, res *lib.Response) (err error) { } // ErrorThing returns status 500 on "/fail" url. This terminated processing chain on reproxy side immediately +// nolint:unparam // error response is required by the interface func (h *Handler) ErrorThing(req lib.Request, res *lib.Response) (err error) { log.Printf("req: %+v", req) if req.URL == "/fail" { diff --git a/examples/plugin/vendor/github.com/go-pkgz/lgr/.golangci.yml b/examples/plugin/vendor/github.com/go-pkgz/lgr/.golangci.yml index 23fd915e..c0e04d0c 100644 --- a/examples/plugin/vendor/github.com/go-pkgz/lgr/.golangci.yml +++ b/examples/plugin/vendor/github.com/go-pkgz/lgr/.golangci.yml @@ -28,24 +28,21 @@ linters-settings: linters: enable: - megacheck - - golint + - revive - govet - unconvert - megacheck - - structcheck - gas - gocyclo - dupl - misspell - unparam - - varcheck - - deadcode + - unused - typecheck - ineffassign - - varcheck - stylecheck - gochecknoinits - - scopelint + - exportloopref - gocritic - nakedret - gosimple diff --git a/examples/plugin/vendor/github.com/go-pkgz/lgr/LICENSE b/examples/plugin/vendor/github.com/go-pkgz/lgr/LICENSE index c1b684bf..dc0ae1a1 100644 --- a/examples/plugin/vendor/github.com/go-pkgz/lgr/LICENSE +++ b/examples/plugin/vendor/github.com/go-pkgz/lgr/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Umputun +Copyright (c) 2023 Umputun Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/examples/plugin/vendor/github.com/go-pkgz/lgr/go.mod b/examples/plugin/vendor/github.com/go-pkgz/lgr/go.mod deleted file mode 100644 index 4ea4d22f..00000000 --- a/examples/plugin/vendor/github.com/go-pkgz/lgr/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module github.com/go-pkgz/lgr - -require github.com/stretchr/testify v1.6.1 - -go 1.15 diff --git a/examples/plugin/vendor/github.com/go-pkgz/lgr/go.sum b/examples/plugin/vendor/github.com/go-pkgz/lgr/go.sum deleted file mode 100644 index 1f1e7af9..00000000 --- a/examples/plugin/vendor/github.com/go-pkgz/lgr/go.sum +++ /dev/null @@ -1,12 +0,0 @@ -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/plugin/vendor/github.com/go-pkgz/lgr/logger.go b/examples/plugin/vendor/github.com/go-pkgz/lgr/logger.go index 9ba12d33..37594378 100644 --- a/examples/plugin/vendor/github.com/go-pkgz/lgr/logger.go +++ b/examples/plugin/vendor/github.com/go-pkgz/lgr/logger.go @@ -2,6 +2,7 @@ // The logger's output can be customized in 2 ways: // - by setting individual formatting flags, i.e. lgr.New(lgr.Msec, lgr.CallerFunc) // - by passing formatting template, i.e. lgr.New(lgr.Format(lgr.Short)) +// // Leveled output works for messages based on text prefix, i.e. Logf("INFO some message") means INFO level. // Debug and trace levels can be filtered based on lgr.Trace and lgr.Debug options. // ERROR, FATAL and PANIC levels send to err as well. FATAL terminate caller application with os.Exit(1) @@ -51,6 +52,7 @@ var ( type Logger struct { // set with Option calls stdout, stderr io.Writer // destination writes for out and err + sameStream bool // stdout and stderr are the same stream dbg bool // allows reporting for DEBUG level trace bool // allows reporting for TRACE and DEBUG levels callerFile bool // reports caller file with line number, i.e. foo/bar.go:89 @@ -128,6 +130,8 @@ func New(options ...Option) *Logger { res.callerOn = strings.Contains(res.format, "{{.Caller") || res.callerFile || res.callerFunc || res.callerPkg res.levelBracesOn = strings.Contains(res.format, "[{{.Level}}]") || res.levelBraces + res.sameStream = isStreamsSame(res.stdout, res.stderr) + return &res } @@ -140,7 +144,7 @@ func (l *Logger) Logf(format string, args ...interface{}) { l.logf(format, args...) } -//nolint gocyclo +// nolint gocyclo func (l *Logger) logf(format string, args ...interface{}) { var lv, msg string @@ -197,7 +201,7 @@ func (l *Logger) logf(format string, args ...interface{}) { // write to err as well for high levels, exit(1) on fatal and panic and dump stack on panic level switch lv { case "ERROR": - if l.stderr != l.stdout { + if !l.sameStream { _, _ = l.stderr.Write(data) } if l.errorDump { @@ -210,12 +214,12 @@ func (l *Logger) logf(format string, args ...interface{}) { } } case "FATAL": - if l.stderr != l.stdout { + if !l.sameStream { _, _ = l.stderr.Write(data) } l.fatal() case "PANIC": - if l.stderr != l.stdout { + if !l.sameStream { _, _ = l.stderr.Write(data) } _, _ = l.stderr.Write(getDump()) @@ -405,3 +409,21 @@ func getDump() []byte { } return stacktrace[:length] } + +// isStreamsSame checks if two streams are the same by comparing file which they refer to +func isStreamsSame(s1, s2 io.Writer) bool { + s1File, outOk := s1.(*os.File) + s2File, errOk := s2.(*os.File) + if outOk && errOk { + outStat, err := s1File.Stat() + if err != nil { + return false + } + errStat, err := s2File.Stat() + if err != nil { + return false + } + return os.SameFile(outStat, errStat) + } + return s1 == s2 +} diff --git a/examples/plugin/vendor/github.com/go-pkgz/lgr/options.go b/examples/plugin/vendor/github.com/go-pkgz/lgr/options.go index 646d4863..16fadacb 100644 --- a/examples/plugin/vendor/github.com/go-pkgz/lgr/options.go +++ b/examples/plugin/vendor/github.com/go-pkgz/lgr/options.go @@ -1,11 +1,14 @@ package lgr -import "io" +import ( + "io" + "strings" +) // Option func type type Option func(l *Logger) -// Out sets out writer, stdout by default +// Out sets output writer, stdout by default func Out(w io.Writer) Option { return func(l *Logger) { l.stdout = w @@ -74,6 +77,9 @@ func Msec(l *Logger) { func Secret(vals ...string) Option { return func(l *Logger) { for _, v := range vals { + if strings.TrimSpace(v) == "" { + continue // skip empty secrets + } l.secrets = append(l.secrets, []byte(v)) } } diff --git a/examples/plugin/vendor/github.com/go-pkgz/repeater/go.mod b/examples/plugin/vendor/github.com/go-pkgz/repeater/go.mod deleted file mode 100644 index 3488d7b9..00000000 --- a/examples/plugin/vendor/github.com/go-pkgz/repeater/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module github.com/go-pkgz/repeater - -go 1.12 - -require github.com/stretchr/testify v1.3.0 diff --git a/examples/plugin/vendor/github.com/go-pkgz/repeater/go.sum b/examples/plugin/vendor/github.com/go-pkgz/repeater/go.sum deleted file mode 100644 index 4347755a..00000000 --- a/examples/plugin/vendor/github.com/go-pkgz/repeater/go.sum +++ /dev/null @@ -1,7 +0,0 @@ -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/examples/plugin/vendor/github.com/umputun/reproxy/lib/plugin.go b/examples/plugin/vendor/github.com/umputun/reproxy/lib/plugin.go index 2e287f2b..5b4441a1 100644 --- a/examples/plugin/vendor/github.com/umputun/reproxy/lib/plugin.go +++ b/examples/plugin/vendor/github.com/umputun/reproxy/lib/plugin.go @@ -23,7 +23,7 @@ type Plugin struct { // Do register the plugin, send info to reproxy conductor and activate RPC listener. // On completion unregister from reproxy. Blocking call, should run in goroutine on the caller side -// rvcr is provided struct implemented at least one RPC methods with teh signature leike this: +// rvcr is provided struct implemented at least one RPC methods with the signature like this: // func(req lib.Request, res *lib.Response) (err error) // see [examples/plugin]() for more info func (p *Plugin) Do(ctx context.Context, conductor string, rcvr interface{}) (err error) { @@ -39,7 +39,7 @@ func (p *Plugin) Do(ctx context.Context, conductor string, rcvr interface{}) (er client := http.Client{Timeout: time.Second} time.AfterFunc(time.Millisecond*50, func() { // registration http call delayed to let listener time to start - err := repeater.NewDefault(10, time.Millisecond*500).Do(ctx, func() error { + err = repeater.NewDefault(10, time.Millisecond*500).Do(ctx, func() error { return p.send(&client, conductor, "POST") }) if err != nil { @@ -63,6 +63,13 @@ func (p *Plugin) listen(ctx context.Context) error { return fmt.Errorf("can't listen on %s: %v", p.Address, err) } + go func() { + <-ctx.Done() + if err := listener.Close(); err != nil { + log.Printf("[WARN] can't lose plugin listener") + } + }() + for { log.Printf("[DEBUG] plugin listener for %s:%s activated", p.Name, p.Address) conn, err := listener.Accept() @@ -78,7 +85,7 @@ func (p *Plugin) listen(ctx context.Context) error { } } -func (p *Plugin) send(client *http.Client, conductor string, method string) error { +func (p *Plugin) send(client *http.Client, conductor, method string) error { if conductor == "" { return nil @@ -96,7 +103,7 @@ func (p *Plugin) send(client *http.Client, conductor string, method string) erro if err != nil { return err } - defer resp.Body.Close() + defer resp.Body.Close() // nolint if resp.StatusCode != http.StatusOK { return fmt.Errorf("invalid status %s", resp.Status) diff --git a/examples/plugin/vendor/github.com/umputun/reproxy/lib/rpc.go b/examples/plugin/vendor/github.com/umputun/reproxy/lib/rpc.go index 9fd2b8f3..54cc8d80 100644 --- a/examples/plugin/vendor/github.com/umputun/reproxy/lib/rpc.go +++ b/examples/plugin/vendor/github.com/umputun/reproxy/lib/rpc.go @@ -25,7 +25,9 @@ type Request struct { // Response from plugin's handler call type Response struct { - StatusCode int - HeadersIn http.Header - HeadersOut http.Header + StatusCode int + HeadersIn http.Header + HeadersOut http.Header + OverrideHeadersIn bool // indicates plugin removing all the original incoming headers + OverrideHeadersOut bool // indicates plugin removing all the original outgoing headers } diff --git a/examples/plugin/vendor/modules.txt b/examples/plugin/vendor/modules.txt index a6b92a02..93bc6812 100644 --- a/examples/plugin/vendor/modules.txt +++ b/examples/plugin/vendor/modules.txt @@ -1,9 +1,11 @@ -# github.com/go-pkgz/lgr v0.10.4 +# github.com/go-pkgz/lgr v0.11.1 +## explicit; go 1.20 github.com/go-pkgz/lgr # github.com/go-pkgz/repeater v1.1.3 +## explicit; go 1.12 github.com/go-pkgz/repeater github.com/go-pkgz/repeater/strategy -# github.com/umputun/reproxy v0.6.0 => ../../ -## explicit +# github.com/umputun/reproxy v0.999.0 => ../../ +## explicit; go 1.22 github.com/umputun/reproxy/lib # github.com/umputun/reproxy => ../../