From fb467eb9a5f57826059c6c7af714d80ae3b2ee00 Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Tue, 25 Mar 2025 22:46:04 +0300 Subject: [PATCH 01/10] chore: upgrade .golangci.yml and workflow to v2 run `golangci-lint fmt` Signed-off-by: Mohammed Al Sahaf --- .github/workflows/lint.yml | 2 +- .golangci.yml | 235 +++++++----------- caddytest/integration/acme_test.go | 5 +- caddytest/integration/acmeserver_test.go | 3 +- caddytest/integration/caddyfile_adapt_test.go | 1 - caddytest/integration/caddyfile_test.go | 1 - caddytest/integration/mockdns_test.go | 15 +- caddytest/integration/stream_test.go | 3 +- cmd/main_test.go | 3 - listeners_test.go | 14 +- modules/caddyhttp/metrics_test.go | 3 +- .../caddyhttp/reverseproxy/upstreams_test.go | 1 - modules/caddyhttp/server_test.go | 1 + modules/caddytls/ech_test.go | 1 - modules/logging/filewriter_test.go | 4 +- modules/logging/filters_test.go | 3 +- 16 files changed, 114 insertions(+), 181 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c5c89b50234..cb05c4c6506 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -51,7 +51,7 @@ jobs: check-latest: true - name: golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v7 with: version: latest diff --git a/.golangci.yml b/.golangci.yml index aecff563eed..5609f844e6c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,27 +1,15 @@ -linters-settings: - errcheck: - exclude-functions: - - fmt.* - - (go.uber.org/zap/zapcore.ObjectEncoder).AddObject - - (go.uber.org/zap/zapcore.ObjectEncoder).AddArray - gci: - sections: - - standard # Standard section: captures all standard packages. - - default # Default section: contains all imports that could not be matched to another section type. - - prefix(github.com/caddyserver/caddy/v2/cmd) # ensure that this is always at the top and always has a line break. - - prefix(github.com/caddyserver/caddy) # Custom section: groups all imports with the specified Prefix. - # Skip generated files. - # Default: true - skip-generated: true - # Enable custom order of sections. - # If `true`, make the section order the same as the order of `sections`. - # Default: false - custom-order: true - exhaustive: - ignore-enum-types: reflect.Kind|svc.Cmd - +version: "2" +run: + issues-exit-code: 1 + tests: false +output: + formats: + text: + path: stdout + print-linter-name: true + print-issued-lines: true linters: - disable-all: true + default: none enable: - asasalint - asciicheck @@ -35,148 +23,93 @@ linters: - errcheck - errname - exhaustive - - gci - - gofmt - - goimports - - gofumpt - gosec - - gosimple - govet - - ineffassign - importas + - ineffassign - misspell - prealloc - promlinter - sloglint - sqlclosecheck - staticcheck - - tenv - testableexamples - testifylint - tparallel - - typecheck - unconvert - unused - wastedassign - whitespace - zerologlint - # these are implicitly disabled: - # - containedctx - # - contextcheck - # - cyclop - # - depguard - # - errchkjson - # - errorlint - # - exhaustruct - # - execinquery - # - exhaustruct - # - forbidigo - # - forcetypeassert - # - funlen - # - ginkgolinter - # - gocheckcompilerdirectives - # - gochecknoglobals - # - gochecknoinits - # - gochecksumtype - # - gocognit - # - goconst - # - gocritic - # - gocyclo - # - godot - # - godox - # - goerr113 - # - goheader - # - gomnd - # - gomoddirectives - # - gomodguard - # - goprintffuncname - # - gosmopolitan - # - grouper - # - inamedparam - # - interfacebloat - # - ireturn - # - lll - # - loggercheck - # - maintidx - # - makezero - # - mirror - # - musttag - # - nakedret - # - nestif - # - nilerr - # - nilnil - # - nlreturn - # - noctx - # - nolintlint - # - nonamedreturns - # - nosprintfhostport - # - paralleltest - # - perfsprint - # - predeclared - # - protogetter - # - reassign - # - revive - # - rowserrcheck - # - stylecheck - # - tagalign - # - tagliatelle - # - testpackage - # - thelper - # - unparam - # - usestdlibvars - # - varnamelen - # - wrapcheck - # - wsl - -run: - # default concurrency is a available CPU number. - # concurrency: 4 # explicitly omit this value to fully utilize available resources. - timeout: 5m - issues-exit-code: 1 - tests: false - -# output configuration options -output: - formats: - - format: 'colored-line-number' - print-issued-lines: true - print-linter-name: true - -issues: - exclude-rules: - - text: 'G115' # TODO: Either we should fix the issues or nuke the linter if it's bad - linters: - - gosec - # we aren't calling unknown URL - - text: 'G107' # G107: Url provided to HTTP request as taint input - linters: - - gosec - # as a web server that's expected to handle any template, this is totally in the hands of the user. - - text: 'G203' # G203: Use of unescaped data in HTML templates - linters: - - gosec - # we're shelling out to known commands, not relying on user-defined input. - - text: 'G204' # G204: Audit use of command execution - linters: - - gosec - # the choice of weakrand is deliberate, hence the named import "weakrand" - - path: modules/caddyhttp/reverseproxy/selectionpolicies.go - text: 'G404' # G404: Insecure random number source (rand) - linters: - - gosec - - path: modules/caddyhttp/reverseproxy/streaming.go - text: 'G404' # G404: Insecure random number source (rand) - linters: - - gosec - - path: modules/logging/filters.go - linters: - - dupl - - path: modules/caddyhttp/matchers.go - linters: - - dupl - - path: modules/caddyhttp/vars.go - linters: - - dupl - - path: _test\.go - linters: - - errcheck + settings: + errcheck: + exclude-functions: + - fmt.* + - (go.uber.org/zap/zapcore.ObjectEncoder).AddObject + - (go.uber.org/zap/zapcore.ObjectEncoder).AddArray + exhaustive: + ignore-enum-types: reflect.Kind|svc.Cmd + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - linters: + - gosec + text: G115 + - linters: + - gosec + text: G107 + - linters: + - gosec + text: G203 + - linters: + - gosec + text: G204 + - linters: + - gosec + path: modules/caddyhttp/reverseproxy/selectionpolicies.go + text: G404 + - linters: + - gosec + path: modules/caddyhttp/reverseproxy/streaming.go + text: G404 + - linters: + - dupl + path: modules/logging/filters.go + - linters: + - dupl + path: modules/caddyhttp/matchers.go + - linters: + - dupl + path: modules/caddyhttp/vars.go + - linters: + - errcheck + path: _test\.go + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gci + - gofmt + - gofumpt + - goimports + settings: + gci: + sections: + - standard + - default + - prefix(github.com/caddyserver/caddy/v2/cmd) + - prefix(github.com/caddyserver/caddy) + custom-order: true + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/caddytest/integration/acme_test.go b/caddytest/integration/acme_test.go index d7e4c296d50..f10aef6a86d 100644 --- a/caddytest/integration/acme_test.go +++ b/caddytest/integration/acme_test.go @@ -12,13 +12,14 @@ import ( "strings" "testing" - "github.com/caddyserver/caddy/v2" - "github.com/caddyserver/caddy/v2/caddytest" "github.com/mholt/acmez/v3" "github.com/mholt/acmez/v3/acme" smallstepacme "github.com/smallstep/certificates/acme" "go.uber.org/zap" "go.uber.org/zap/exp/zapslog" + + "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/caddytest" ) const acmeChallengePort = 9081 diff --git a/caddytest/integration/acmeserver_test.go b/caddytest/integration/acmeserver_test.go index ca5845f8711..d6a9ba005ad 100644 --- a/caddytest/integration/acmeserver_test.go +++ b/caddytest/integration/acmeserver_test.go @@ -9,11 +9,12 @@ import ( "strings" "testing" - "github.com/caddyserver/caddy/v2/caddytest" "github.com/mholt/acmez/v3" "github.com/mholt/acmez/v3/acme" "go.uber.org/zap" "go.uber.org/zap/exp/zapslog" + + "github.com/caddyserver/caddy/v2/caddytest" ) func TestACMEServerDirectory(t *testing.T) { diff --git a/caddytest/integration/caddyfile_adapt_test.go b/caddytest/integration/caddyfile_adapt_test.go index 0d9f0fa471d..674036e1707 100644 --- a/caddytest/integration/caddyfile_adapt_test.go +++ b/caddytest/integration/caddyfile_adapt_test.go @@ -10,7 +10,6 @@ import ( "testing" "github.com/caddyserver/caddy/v2/caddytest" - _ "github.com/caddyserver/caddy/v2/internal/testmocks" ) diff --git a/caddytest/integration/caddyfile_test.go b/caddytest/integration/caddyfile_test.go index 11ffc08aeb1..b340eb8c501 100644 --- a/caddytest/integration/caddyfile_test.go +++ b/caddytest/integration/caddyfile_test.go @@ -615,7 +615,6 @@ func TestReplaceWithReplacementPlaceholder(t *testing.T) { respond "{query}"`, "caddyfile") tester.AssertGetResponse("http://localhost:9080/endpoint?placeholder=baz&foo=bar", 200, "foo=baz&placeholder=baz") - } func TestReplaceWithKeyPlaceholder(t *testing.T) { diff --git a/caddytest/integration/mockdns_test.go b/caddytest/integration/mockdns_test.go index 615116a3aec..31dc4be7bc1 100644 --- a/caddytest/integration/mockdns_test.go +++ b/caddytest/integration/mockdns_test.go @@ -3,10 +3,11 @@ package integration import ( "context" - "github.com/caddyserver/caddy/v2" - "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/certmagic" "github.com/libdns/libdns" + + "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" ) func init() { @@ -55,7 +56,9 @@ func (MockDNSProvider) SetRecords(ctx context.Context, zone string, recs []libdn } // Interface guard -var _ caddyfile.Unmarshaler = (*MockDNSProvider)(nil) -var _ certmagic.DNSProvider = (*MockDNSProvider)(nil) -var _ caddy.Provisioner = (*MockDNSProvider)(nil) -var _ caddy.Module = (*MockDNSProvider)(nil) +var ( + _ caddyfile.Unmarshaler = (*MockDNSProvider)(nil) + _ certmagic.DNSProvider = (*MockDNSProvider)(nil) + _ caddy.Provisioner = (*MockDNSProvider)(nil) + _ caddy.Module = (*MockDNSProvider)(nil) +) diff --git a/caddytest/integration/stream_test.go b/caddytest/integration/stream_test.go index d2f2fd79b95..57231a5271b 100644 --- a/caddytest/integration/stream_test.go +++ b/caddytest/integration/stream_test.go @@ -13,9 +13,10 @@ import ( "testing" "time" - "github.com/caddyserver/caddy/v2/caddytest" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" + + "github.com/caddyserver/caddy/v2/caddytest" ) // (see https://github.com/caddyserver/caddy/issues/3556 for use case) diff --git a/cmd/main_test.go b/cmd/main_test.go index 3b2412c57e9..bff34f443ad 100644 --- a/cmd/main_test.go +++ b/cmd/main_test.go @@ -235,7 +235,6 @@ func Test_isCaddyfile(t *testing.T) { wantErr: false, }, { - name: "json is not caddyfile but not error", args: args{ configFile: "./Caddyfile.json", @@ -245,7 +244,6 @@ func Test_isCaddyfile(t *testing.T) { wantErr: false, }, { - name: "prefix of Caddyfile and ./ with any extension is Caddyfile", args: args{ configFile: "./Caddyfile.prd", @@ -255,7 +253,6 @@ func Test_isCaddyfile(t *testing.T) { wantErr: false, }, { - name: "prefix of Caddyfile without ./ with any extension is Caddyfile", args: args{ configFile: "Caddyfile.prd", diff --git a/listeners_test.go b/listeners_test.go index 03945308e40..a4cadd3aab1 100644 --- a/listeners_test.go +++ b/listeners_test.go @@ -30,7 +30,7 @@ func TestSplitNetworkAddress(t *testing.T) { expectErr bool }{ { - input: "", + input: "", expectHost: "", }, { @@ -41,7 +41,7 @@ func TestSplitNetworkAddress(t *testing.T) { input: ":", // empty host & empty port }, { - input: "::", + input: "::", expectHost: "::", }, { @@ -184,9 +184,8 @@ func TestParseNetworkAddress(t *testing.T) { expectErr bool }{ { - input: "", - expectAddr: NetworkAddress{ - }, + input: "", + expectAddr: NetworkAddress{}, }, { input: ":", @@ -311,9 +310,8 @@ func TestParseNetworkAddressWithDefaults(t *testing.T) { expectErr bool }{ { - input: "", - expectAddr: NetworkAddress{ - }, + input: "", + expectAddr: NetworkAddress{}, }, { input: ":", diff --git a/modules/caddyhttp/metrics_test.go b/modules/caddyhttp/metrics_test.go index 4a0519b8769..4e1aa8b3037 100644 --- a/modules/caddyhttp/metrics_test.go +++ b/modules/caddyhttp/metrics_test.go @@ -9,8 +9,9 @@ import ( "sync" "testing" - "github.com/caddyserver/caddy/v2" "github.com/prometheus/client_golang/prometheus/testutil" + + "github.com/caddyserver/caddy/v2" ) func TestServerNameFromContext(t *testing.T) { diff --git a/modules/caddyhttp/reverseproxy/upstreams_test.go b/modules/caddyhttp/reverseproxy/upstreams_test.go index 48e2d2a6310..8caf8696a1c 100644 --- a/modules/caddyhttp/reverseproxy/upstreams_test.go +++ b/modules/caddyhttp/reverseproxy/upstreams_test.go @@ -52,5 +52,4 @@ func TestResolveIpVersion(t *testing.T) { t.Errorf("resolveIpVersion(): Expected %s got %s", test.expectedIpVersion, ipVersion) } } - } diff --git a/modules/caddyhttp/server_test.go b/modules/caddyhttp/server_test.go index 53f35368f93..6ce09974be5 100644 --- a/modules/caddyhttp/server_test.go +++ b/modules/caddyhttp/server_test.go @@ -171,6 +171,7 @@ func BenchmarkServer_LogRequest_WithTrace(b *testing.B) { s.logRequest(accLog, req, wrec, &duration, repl, bodyReader, false) } } + func TestServer_TrustedRealClientIP_NoTrustedHeaders(t *testing.T) { req := httptest.NewRequest("GET", "/", nil) req.RemoteAddr = "192.0.2.1:12345" diff --git a/modules/caddytls/ech_test.go b/modules/caddytls/ech_test.go index b722d2fbfa6..3e566f5a762 100644 --- a/modules/caddytls/ech_test.go +++ b/modules/caddytls/ech_test.go @@ -76,7 +76,6 @@ func TestSvcParamsString(t *testing.T) { // because we can't just compare string outputs // since map iteration is unordered for i, test := range []svcParams{ - { "alpn": {"h2", "h3"}, "no-default-alpn": {}, diff --git a/modules/logging/filewriter_test.go b/modules/logging/filewriter_test.go index f9072f98a1c..2a246156c95 100644 --- a/modules/logging/filewriter_test.go +++ b/modules/logging/filewriter_test.go @@ -317,7 +317,7 @@ func TestFileModeToJSON(t *testing.T) { }{ { name: "none zero", - mode: 0644, + mode: 0o644, want: `"0644"`, wantErr: false, }, @@ -358,7 +358,7 @@ func TestFileModeModification(t *testing.T) { defer os.RemoveAll(dir) fpath := path.Join(dir, "test.log") - f_tmp, err := os.OpenFile(fpath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(0600)) + f_tmp, err := os.OpenFile(fpath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(0o600)) if err != nil { t.Fatalf("failed to create test file: %v", err) } diff --git a/modules/logging/filters_test.go b/modules/logging/filters_test.go index 8f7ba0d7071..a929617d7e0 100644 --- a/modules/logging/filters_test.go +++ b/modules/logging/filters_test.go @@ -3,9 +3,10 @@ package logging import ( "testing" + "go.uber.org/zap/zapcore" + "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/modules/caddyhttp" - "go.uber.org/zap/zapcore" ) func TestIPMaskSingleValue(t *testing.T) { From 9e284a5b0b8303dd3b264d71b5555bbd06df2f12 Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Tue, 25 Mar 2025 22:55:56 +0300 Subject: [PATCH 02/10] run `golangci-lint run --fix` Signed-off-by: Mohammed Al Sahaf --- caddyconfig/caddyfile/adapter.go | 2 +- caddyconfig/caddyfile/formatter.go | 2 +- caddyconfig/caddyfile/lexer.go | 2 +- caddyconfig/caddyfile/parse.go | 4 ++-- caddyconfig/httpcaddyfile/builtins.go | 2 +- caddyconfig/httpcaddyfile/directives.go | 11 ++++++----- caddytest/caddytest.go | 2 +- cmd/main.go | 4 ++-- cmd/packagesfuncs.go | 2 +- listeners.go | 4 ++-- logging.go | 6 +++--- modules/caddyevents/app.go | 7 ++----- modules/caddyhttp/autohttps.go | 2 +- modules/caddyhttp/celmatcher.go | 4 ++-- modules/caddyhttp/fileserver/matcher.go | 9 +++++---- modules/caddyhttp/headers/caddyfile.go | 2 +- modules/caddyhttp/headers/headers.go | 4 ++-- modules/caddyhttp/matchers.go | 5 +---- modules/caddyhttp/push/handler.go | 2 +- modules/caddyhttp/replacer.go | 6 +++--- modules/caddyhttp/responsewriter.go | 2 +- modules/caddyhttp/reverseproxy/caddyfile.go | 5 +++-- modules/caddyhttp/reverseproxy/command.go | 5 +++-- modules/caddyhttp/reverseproxy/healthchecks.go | 14 +++++++------- modules/caddyhttp/reverseproxy/hosts.go | 4 ++-- modules/caddyhttp/reverseproxy/httptransport.go | 4 ++-- modules/caddyhttp/reverseproxy/reverseproxy.go | 10 +++++----- .../caddyhttp/reverseproxy/selectionpolicies.go | 2 +- modules/caddyhttp/rewrite/rewrite.go | 5 +---- modules/caddytls/automation.go | 6 ++---- modules/logging/netwriter.go | 2 +- 31 files changed, 67 insertions(+), 74 deletions(-) diff --git a/caddyconfig/caddyfile/adapter.go b/caddyconfig/caddyfile/adapter.go index da4f98337fb..449370dc6ce 100644 --- a/caddyconfig/caddyfile/adapter.go +++ b/caddyconfig/caddyfile/adapter.go @@ -68,7 +68,7 @@ func (a Adapter) Adapt(body []byte, options map[string]any) ([]byte, []caddyconf // TODO: also perform this check on imported files func FormattingDifference(filename string, body []byte) (caddyconfig.Warning, bool) { // replace windows-style newlines to normalize comparison - normalizedBody := bytes.Replace(body, []byte("\r\n"), []byte("\n"), -1) + normalizedBody := bytes.ReplaceAll(body, []byte("\r\n"), []byte("\n")) formatted := Format(normalizedBody) if bytes.Equal(formatted, normalizedBody) { diff --git a/caddyconfig/caddyfile/formatter.go b/caddyconfig/caddyfile/formatter.go index f1d12fa51aa..0476a9b9310 100644 --- a/caddyconfig/caddyfile/formatter.go +++ b/caddyconfig/caddyfile/formatter.go @@ -94,7 +94,7 @@ func Format(input []byte) []byte { } // detect whether we have the start of a heredoc - if !quoted && !(heredoc != heredocClosed || heredocEscaped) && + if !quoted && (heredoc == heredocClosed && !heredocEscaped) && space && last == '<' && ch == '<' { write(ch) heredoc = heredocOpening diff --git a/caddyconfig/caddyfile/lexer.go b/caddyconfig/caddyfile/lexer.go index 9b523f397ad..a3b1fc7db7f 100644 --- a/caddyconfig/caddyfile/lexer.go +++ b/caddyconfig/caddyfile/lexer.go @@ -137,7 +137,7 @@ func (l *lexer) next() (bool, error) { } // detect whether we have the start of a heredoc - if !(quoted || btQuoted) && !(inHeredoc || heredocEscaped) && + if (!quoted && !btQuoted) && (!inHeredoc && !heredocEscaped) && len(val) > 1 && string(val[:2]) == "<<" { // a space means it's just a regular token and not a heredoc if ch == ' ' { diff --git a/caddyconfig/caddyfile/parse.go b/caddyconfig/caddyfile/parse.go index d04a1ac4672..784e4acd981 100644 --- a/caddyconfig/caddyfile/parse.go +++ b/caddyconfig/caddyfile/parse.go @@ -423,9 +423,9 @@ func (p *parser) doImport(nesting int) error { // make path relative to the file of the _token_ being processed rather // than current working directory (issue #867) and then use glob to get // list of matching filenames - absFile, err := caddy.FastAbs(p.Dispenser.File()) + absFile, err := caddy.FastAbs(p.File()) if err != nil { - return p.Errf("Failed to get absolute path of file: %s: %v", p.Dispenser.File(), err) + return p.Errf("Failed to get absolute path of file: %s: %v", p.File(), err) } var matches []string diff --git a/caddyconfig/httpcaddyfile/builtins.go b/caddyconfig/httpcaddyfile/builtins.go index 3fc08b2c898..af481ac4946 100644 --- a/caddyconfig/httpcaddyfile/builtins.go +++ b/caddyconfig/httpcaddyfile/builtins.go @@ -998,7 +998,7 @@ func parseLogHelper(h Helper, globalLogNames map[string]struct{}) ([]ConfigValue cl.WriterRaw = caddyconfig.JSONModuleObject(wo, "output", moduleName, h.warnings) case "sampling": - d := h.Dispenser.NewFromNextSegment() + d := h.NewFromNextSegment() for d.NextArg() { // consume any tokens on the same line, if any. } diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go index f0687a7e937..41723333677 100644 --- a/caddyconfig/httpcaddyfile/directives.go +++ b/caddyconfig/httpcaddyfile/directives.go @@ -173,9 +173,10 @@ func RegisterDirectiveOrder(dir string, position Positional, standardDir string) if d != standardDir { continue } - if position == Before { + switch position { + case Before: newOrder = append(newOrder[:i], append([]string{dir}, newOrder[i:]...)...) - } else if position == After { + case After: newOrder = append(newOrder[:i+1], append([]string{dir}, newOrder[i+1:]...)...) } break @@ -245,7 +246,7 @@ func (h Helper) MatcherToken() (caddy.ModuleMap, bool, error) { if !h.NextArg() { return nil, false, nil } - return matcherSetFromMatcherToken(h.Dispenser.Token(), h.matcherDefs, h.warnings) + return matcherSetFromMatcherToken(h.Token(), h.matcherDefs, h.warnings) } // ExtractMatcherSet is like MatcherToken, except this is a higher-level @@ -264,9 +265,9 @@ func (h Helper) ExtractMatcherSet() (caddy.ModuleMap, error) { // new dispenser should have been made // solely for this directive's tokens, // with no other uses of same slice - h.Dispenser.Delete() + h.Delete() } - h.Dispenser.Reset() // pretend this lookahead never happened + h.Reset() // pretend this lookahead never happened return matcherSet, nil } diff --git a/caddytest/caddytest.go b/caddytest/caddytest.go index 623c45e5ed3..7b56bb281cc 100644 --- a/caddytest/caddytest.go +++ b/caddytest/caddytest.go @@ -281,7 +281,7 @@ func validateTestPrerequisites(tc *Tester) error { tc.t.Cleanup(func() { os.Remove(f.Name()) }) - if _, err := f.WriteString(fmt.Sprintf(initConfig, tc.config.AdminPort)); err != nil { + if _, err := fmt.Fprintf(f, initConfig, tc.config.AdminPort); err != nil { return err } diff --git a/cmd/main.go b/cmd/main.go index 87fa9fb955d..80419d4702e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -302,7 +302,7 @@ type Flags struct { // flag given by name. It panics if the flag is not // in the flag set. func (f Flags) String(name string) string { - return f.FlagSet.Lookup(name).Value.String() + return f.Lookup(name).Value.String() } // Bool returns the boolean representation of the @@ -418,7 +418,7 @@ func parseEnvFile(envInput io.Reader) (map[string]string, error) { // quoted value: support newlines if strings.HasPrefix(val, `"`) || strings.HasPrefix(val, "'") { quote := string(val[0]) - for !(strings.HasSuffix(line, quote) && !strings.HasSuffix(line, `\`+quote)) { + for !strings.HasSuffix(line, quote) || strings.HasSuffix(line, `\`+quote) { val = strings.ReplaceAll(val, `\`+quote, quote) if !scanner.Scan() { break diff --git a/cmd/packagesfuncs.go b/cmd/packagesfuncs.go index 69523200179..cda6f31f6d7 100644 --- a/cmd/packagesfuncs.go +++ b/cmd/packagesfuncs.go @@ -84,7 +84,7 @@ func cmdAddPackage(fl Flags) (int, error) { return caddy.ExitCodeFailedStartup, fmt.Errorf("invalid module name: %v", err) } // only allow a version to be specified if it's different from the existing version - if _, ok := pluginPkgs[module]; ok && !(version != "" && pluginPkgs[module].Version != version) { + if _, ok := pluginPkgs[module]; ok && (version == "" || pluginPkgs[module].Version == version) { return caddy.ExitCodeFailedStartup, fmt.Errorf("package is already added") } pluginPkgs[module] = pluginPackage{Version: version, Path: module} diff --git a/listeners.go b/listeners.go index b22df77ba5a..1a074f6d745 100644 --- a/listeners.go +++ b/listeners.go @@ -574,7 +574,7 @@ type sharedQuicListener struct { // Destruct closes the underlying QUIC listener and its associated net.PacketConn. func (sql *sharedQuicListener) Destruct() error { // close EarlyListener first to stop any operations being done to the net.PacketConn - _ = sql.EarlyListener.Close() + _ = sql.Close() // then close the net.PacketConn return sql.packetConn.Close() } @@ -626,7 +626,7 @@ func (fcql *fakeCloseQuicListener) Accept(_ context.Context) (quic.EarlyConnecti func (fcql *fakeCloseQuicListener) Close() error { if atomic.CompareAndSwapInt32(&fcql.closed, 0, 1) { fcql.contextCancel() - _, _ = listenerPool.Delete(fcql.sharedQuicListener.key) + _, _ = listenerPool.Delete(fcql.key) } return nil } diff --git a/logging.go b/logging.go index ca10beeeddc..6bc9f10f2de 100644 --- a/logging.go +++ b/logging.go @@ -151,17 +151,17 @@ func (logging *Logging) setupNewDefault(ctx Context) error { } // options for the default logger - options, err := newDefault.CustomLog.buildOptions() + options, err := newDefault.buildOptions() if err != nil { return fmt.Errorf("setting up default log: %v", err) } // set up this new log - err = newDefault.CustomLog.provision(ctx, logging) + err = newDefault.provision(ctx, logging) if err != nil { return fmt.Errorf("setting up default log: %v", err) } - newDefault.logger = zap.New(newDefault.CustomLog.core, options...) + newDefault.logger = zap.New(newDefault.core, options...) // redirect the default caddy logs defaultLoggerMu.Lock() diff --git a/modules/caddyevents/app.go b/modules/caddyevents/app.go index e78b00f8cfe..398c10f1b07 100644 --- a/modules/caddyevents/app.go +++ b/modules/caddyevents/app.go @@ -229,7 +229,7 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) E zap.String("origin", e.origin.CaddyModule().String())) // add event info to replacer, make sure it's in the context - repl, ok := ctx.Context.Value(caddy.ReplacerCtxKey).(*caddy.Replacer) + repl, ok := ctx.Value(caddy.ReplacerCtxKey).(*caddy.Replacer) if !ok { repl = caddy.NewReplacer() ctx.Context = context.WithValue(ctx.Context, caddy.ReplacerCtxKey, repl) @@ -272,10 +272,7 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) E moduleID := e.origin.CaddyModule().ID // implement propagation up the module tree (i.e. start with "a.b.c" then "a.b" then "a" then "") - for { - if app.subscriptions[eventName] == nil { - break // shortcut if event not bound at all - } + for app.subscriptions[eventName] != nil { for _, handler := range app.subscriptions[eventName][moduleID] { select { diff --git a/modules/caddyhttp/autohttps.go b/modules/caddyhttp/autohttps.go index 769cfd4ef6a..f41d9e6833f 100644 --- a/modules/caddyhttp/autohttps.go +++ b/modules/caddyhttp/autohttps.go @@ -381,7 +381,7 @@ uniqueDomainsLoop: // match on known domain names, unless it's our special case of a // catch-all which is an empty string (common among catch-all sites // that enable on-demand TLS for yet-unknown domain names) - if !(len(domains) == 1 && domains[0] == "") { + if len(domains) != 1 || domains[0] != "" { matcherSet = append(matcherSet, MatchHost(domains)) } diff --git a/modules/caddyhttp/celmatcher.go b/modules/caddyhttp/celmatcher.go index 3d118ea798e..6d7607c4804 100644 --- a/modules/caddyhttp/celmatcher.go +++ b/modules/caddyhttp/celmatcher.go @@ -329,14 +329,14 @@ func (pn celPkixName) ConvertToNative(typeDesc reflect.Type) (any, error) { func (pn celPkixName) ConvertToType(typeVal ref.Type) ref.Val { if typeVal.TypeName() == "string" { - return types.String(pn.Name.String()) + return types.String(pn.String()) } panic("not implemented") } func (pn celPkixName) Equal(other ref.Val) ref.Val { if o, ok := other.Value().(string); ok { - return types.Bool(pn.Name.String() == o) + return types.Bool(pn.String() == o) } return types.ValOrErr(other, "%v is not comparable type", other) } diff --git a/modules/caddyhttp/fileserver/matcher.go b/modules/caddyhttp/fileserver/matcher.go index 2bc665d4f92..638545e253b 100644 --- a/modules/caddyhttp/fileserver/matcher.go +++ b/modules/caddyhttp/fileserver/matcher.go @@ -252,7 +252,7 @@ func celFileMatcherMacroExpander() parser.MacroExpander { } for _, arg := range args { - if !(isCELStringLiteral(arg) || isCELCaddyPlaceholderCall(arg)) { + if !isCELStringLiteral(arg) && !isCELCaddyPlaceholderCall(arg) { return nil, &common.Error{ Location: eh.OffsetLocation(arg.ID()), Message: "matcher only supports repeated string literal arguments", @@ -616,15 +616,16 @@ func isCELTryFilesLiteral(e ast.Expr) bool { return false } mapKeyStr := mapKey.AsLiteral().ConvertToType(types.StringType).Value() - if mapKeyStr == "try_files" || mapKeyStr == "split_path" { + switch mapKeyStr { + case "try_files", "split_path": if !isCELStringListLiteral(mapVal) { return false } - } else if mapKeyStr == "try_policy" || mapKeyStr == "root" { + case "try_policy", "root": if !(isCELStringExpr(mapVal)) { return false } - } else { + default: return false } } diff --git a/modules/caddyhttp/headers/caddyfile.go b/modules/caddyhttp/headers/caddyfile.go index f060471b100..2758f290754 100644 --- a/modules/caddyhttp/headers/caddyfile.go +++ b/modules/caddyhttp/headers/caddyfile.go @@ -87,7 +87,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) if err != nil { return nil, h.Err(err.Error()) } - if len(handler.Response.HeaderOps.Delete) > 0 { + if len(handler.Response.Delete) > 0 { handler.Response.Deferred = true } } diff --git a/modules/caddyhttp/headers/headers.go b/modules/caddyhttp/headers/headers.go index ef9e35e7d4d..5c160c72e33 100644 --- a/modules/caddyhttp/headers/headers.go +++ b/modules/caddyhttp/headers/headers.go @@ -354,9 +354,9 @@ func (rww *responseWriterWrapper) WriteHeader(status int) { if status < 100 || status > 199 { rww.wroteHeader = true } - if rww.require == nil || rww.require.Match(status, rww.ResponseWriterWrapper.Header()) { + if rww.require == nil || rww.require.Match(status, rww.Header()) { if rww.headerOps != nil { - rww.headerOps.ApplyTo(rww.ResponseWriterWrapper.Header(), rww.replacer) + rww.headerOps.ApplyTo(rww.Header(), rww.replacer) } } rww.ResponseWriterWrapper.WriteHeader(status) diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go index 01bd7b8b4de..9dac84b8160 100644 --- a/modules/caddyhttp/matchers.go +++ b/modules/caddyhttp/matchers.go @@ -548,10 +548,7 @@ func (MatchPath) matchPatternWithEscapeSequence(escapedPath, matchPath string) b // increment iPath every time we consume a char from the path; // iPattern and iPath are our cursors/iterator positions for each string var iPattern, iPath int - for { - if iPattern >= len(matchPath) || iPath >= len(escapedPath) { - break - } + for iPattern < len(matchPath) && iPath < len(escapedPath) { // get the next character from the request path diff --git a/modules/caddyhttp/push/handler.go b/modules/caddyhttp/push/handler.go index 1fbe53d8366..a43e767843b 100644 --- a/modules/caddyhttp/push/handler.go +++ b/modules/caddyhttp/push/handler.go @@ -210,7 +210,7 @@ type linkPusher struct { } func (lp linkPusher) WriteHeader(statusCode int) { - if links, ok := lp.ResponseWriter.Header()["Link"]; ok { + if links, ok := lp.Header()["Link"]; ok { // only initiate these pushes if it hasn't been done yet if val := caddyhttp.GetVar(lp.request.Context(), pushedLink); val == nil { if c := lp.handler.logger.Check(zapcore.DebugLevel, "pushing Link resources"); c != nil { diff --git a/modules/caddyhttp/replacer.go b/modules/caddyhttp/replacer.go index 776aa6294b3..69779e6edc3 100644 --- a/modules/caddyhttp/replacer.go +++ b/modules/caddyhttp/replacer.go @@ -363,13 +363,13 @@ func addHTTPVarsToReplacer(repl *caddy.Replacer, req *http.Request, w http.Respo } } - switch { - case key == "http.shutting_down": + switch key { + case "http.shutting_down": server := req.Context().Value(ServerCtxKey).(*Server) server.shutdownAtMu.RLock() defer server.shutdownAtMu.RUnlock() return !server.shutdownAt.IsZero(), true - case key == "http.time_until_shutdown": + case "http.time_until_shutdown": server := req.Context().Value(ServerCtxKey).(*Server) server.shutdownAtMu.RLock() defer server.shutdownAtMu.RUnlock() diff --git a/modules/caddyhttp/responsewriter.go b/modules/caddyhttp/responsewriter.go index 904c30c0352..e9d0e0739ec 100644 --- a/modules/caddyhttp/responsewriter.go +++ b/modules/caddyhttp/responsewriter.go @@ -158,7 +158,7 @@ func (rr *responseRecorder) WriteHeader(statusCode int) { if rr.shouldBuffer == nil { rr.stream = true } else { - rr.stream = !rr.shouldBuffer(rr.statusCode, rr.ResponseWriterWrapper.Header()) + rr.stream = !rr.shouldBuffer(rr.statusCode, rr.Header()) } // 1xx responses aren't final; just informational diff --git a/modules/caddyhttp/reverseproxy/caddyfile.go b/modules/caddyhttp/reverseproxy/caddyfile.go index d0947197ac0..8439d1d5157 100644 --- a/modules/caddyhttp/reverseproxy/caddyfile.go +++ b/modules/caddyhttp/reverseproxy/caddyfile.go @@ -665,9 +665,10 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { if d.NextArg() { return d.ArgErr() } - if subdir == "request_buffers" { + switch subdir { + case "request_buffers": h.RequestBuffers = size - } else if subdir == "response_buffers" { + case "response_buffers": h.ResponseBuffers = size } diff --git a/modules/caddyhttp/reverseproxy/command.go b/modules/caddyhttp/reverseproxy/command.go index f9304efa20b..54955bcf70b 100644 --- a/modules/caddyhttp/reverseproxy/command.go +++ b/modules/caddyhttp/reverseproxy/command.go @@ -122,9 +122,10 @@ func cmdReverseProxy(fs caddycmd.Flags) (int, error) { } } if fromAddr.Port == "" { - if fromAddr.Scheme == "http" { + switch fromAddr.Scheme { + case "http": fromAddr.Port = httpPort - } else if fromAddr.Scheme == "https" { + case "https": fromAddr.Port = httpsPort } } diff --git a/modules/caddyhttp/reverseproxy/healthchecks.go b/modules/caddyhttp/reverseproxy/healthchecks.go index f0ffee5b8f7..a27fc44f0ea 100644 --- a/modules/caddyhttp/reverseproxy/healthchecks.go +++ b/modules/caddyhttp/reverseproxy/healthchecks.go @@ -451,7 +451,7 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, networ markUnhealthy := func() { // increment failures and then check if it has reached the threshold to mark unhealthy - err := upstream.Host.countHealthFail(1) + err := upstream.countHealthFail(1) if err != nil { if c := h.HealthChecks.Active.logger.Check(zapcore.ErrorLevel, "could not count active health failure"); c != nil { c.Write( @@ -461,18 +461,18 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, networ } return } - if upstream.Host.activeHealthFails() >= h.HealthChecks.Active.Fails { + if upstream.activeHealthFails() >= h.HealthChecks.Active.Fails { // dispatch an event that the host newly became unhealthy if upstream.setHealthy(false) { h.events.Emit(h.ctx, "unhealthy", map[string]any{"host": hostAddr}) - upstream.Host.resetHealth() + upstream.resetHealth() } } } markHealthy := func() { // increment passes and then check if it has reached the threshold to be healthy - err := upstream.Host.countHealthPass(1) + err := upstream.countHealthPass(1) if err != nil { if c := h.HealthChecks.Active.logger.Check(zapcore.ErrorLevel, "could not count active health pass"); c != nil { c.Write( @@ -482,13 +482,13 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, networ } return } - if upstream.Host.activeHealthPasses() >= h.HealthChecks.Active.Passes { + if upstream.activeHealthPasses() >= h.HealthChecks.Active.Passes { if upstream.setHealthy(true) { if c := h.HealthChecks.Active.logger.Check(zapcore.InfoLevel, "host is up"); c != nil { c.Write(zap.String("host", hostAddr)) } h.events.Emit(h.ctx, "healthy", map[string]any{"host": hostAddr}) - upstream.Host.resetHealth() + upstream.resetHealth() } } } @@ -584,7 +584,7 @@ func (h *Handler) countFailure(upstream *Upstream) { } // count failure immediately - err := upstream.Host.countFail(1) + err := upstream.countFail(1) if err != nil { if c := h.HealthChecks.Active.logger.Check(zapcore.ErrorLevel, "could not count failure"); c != nil { c.Write( diff --git a/modules/caddyhttp/reverseproxy/hosts.go b/modules/caddyhttp/reverseproxy/hosts.go index 0a676e43147..76cc7ac9fb7 100644 --- a/modules/caddyhttp/reverseproxy/hosts.go +++ b/modules/caddyhttp/reverseproxy/hosts.go @@ -84,7 +84,7 @@ func (u *Upstream) Available() bool { func (u *Upstream) Healthy() bool { healthy := u.healthy() if healthy && u.healthCheckPolicy != nil { - healthy = u.Host.Fails() < u.healthCheckPolicy.MaxFails + healthy = u.Fails() < u.healthCheckPolicy.MaxFails } if healthy && u.cb != nil { healthy = u.cb.OK() @@ -95,7 +95,7 @@ func (u *Upstream) Healthy() bool { // Full returns true if the remote host // cannot receive more requests at this time. func (u *Upstream) Full() bool { - return u.MaxRequests > 0 && u.Host.NumRequests() >= u.MaxRequests + return u.MaxRequests > 0 && u.NumRequests() >= u.MaxRequests } // fillDialInfo returns a filled DialInfo for upstream u, using the request diff --git a/modules/caddyhttp/reverseproxy/httptransport.go b/modules/caddyhttp/reverseproxy/httptransport.go index 92fe9ab7c5b..5198f6908f1 100644 --- a/modules/caddyhttp/reverseproxy/httptransport.go +++ b/modules/caddyhttp/reverseproxy/httptransport.go @@ -774,7 +774,7 @@ type tcpRWTimeoutConn struct { func (c *tcpRWTimeoutConn) Read(b []byte) (int, error) { if c.readTimeout > 0 { - err := c.TCPConn.SetReadDeadline(time.Now().Add(c.readTimeout)) + err := c.SetReadDeadline(time.Now().Add(c.readTimeout)) if err != nil { if ce := c.logger.Check(zapcore.ErrorLevel, "failed to set read deadline"); ce != nil { ce.Write(zap.Error(err)) @@ -786,7 +786,7 @@ func (c *tcpRWTimeoutConn) Read(b []byte) (int, error) { func (c *tcpRWTimeoutConn) Write(b []byte) (int, error) { if c.writeTimeout > 0 { - err := c.TCPConn.SetWriteDeadline(time.Now().Add(c.writeTimeout)) + err := c.SetWriteDeadline(time.Now().Add(c.writeTimeout)) if err != nil { if ce := c.logger.Check(zapcore.ErrorLevel, "failed to set write deadline"); ce != nil { ce.Write(zap.Error(err)) diff --git a/modules/caddyhttp/reverseproxy/reverseproxy.go b/modules/caddyhttp/reverseproxy/reverseproxy.go index 5bdafa070d7..395d6e4ebbe 100644 --- a/modules/caddyhttp/reverseproxy/reverseproxy.go +++ b/modules/caddyhttp/reverseproxy/reverseproxy.go @@ -554,9 +554,9 @@ func (h *Handler) proxyLoopIteration(r *http.Request, origReq *http.Request, w h repl.Set("http.reverse_proxy.upstream.hostport", dialInfo.Address) repl.Set("http.reverse_proxy.upstream.host", dialInfo.Host) repl.Set("http.reverse_proxy.upstream.port", dialInfo.Port) - repl.Set("http.reverse_proxy.upstream.requests", upstream.Host.NumRequests()) + repl.Set("http.reverse_proxy.upstream.requests", upstream.NumRequests()) repl.Set("http.reverse_proxy.upstream.max_requests", upstream.MaxRequests) - repl.Set("http.reverse_proxy.upstream.fails", upstream.Host.Fails()) + repl.Set("http.reverse_proxy.upstream.fails", upstream.Fails()) // mutate request headers according to this upstream; // because we're in a retry loop, we have to copy @@ -827,9 +827,9 @@ func (h Handler) addForwardedHeaders(req *http.Request) error { // (This method is mostly the beginning of what was borrowed from the net/http/httputil package in the // Go standard library which was used as the foundation.) func (h *Handler) reverseProxy(rw http.ResponseWriter, req *http.Request, origReq *http.Request, repl *caddy.Replacer, di DialInfo, next caddyhttp.Handler) error { - _ = di.Upstream.Host.countRequest(1) + _ = di.Upstream.countRequest(1) //nolint:errcheck - defer di.Upstream.Host.countRequest(-1) + defer di.Upstream.countRequest(-1) // point the request to this upstream h.directRequest(req, di) @@ -1150,7 +1150,7 @@ func (lb LoadBalancing) tryAgain(ctx caddy.Context, start time.Time, retries int // we have to assume the upstream received the request, and // retries need to be carefully decided, because some requests // are not idempotent - if !isDialError && !(isHandlerError && errors.Is(herr, errNoUpstream)) { + if !isDialError && (!isHandlerError || !errors.Is(herr, errNoUpstream)) { if lb.RetryMatch == nil && req.Method != "GET" { // by default, don't retry requests if they aren't GET return false diff --git a/modules/caddyhttp/reverseproxy/selectionpolicies.go b/modules/caddyhttp/reverseproxy/selectionpolicies.go index fcf7f90f647..a9c036596e8 100644 --- a/modules/caddyhttp/reverseproxy/selectionpolicies.go +++ b/modules/caddyhttp/reverseproxy/selectionpolicies.go @@ -808,7 +808,7 @@ func leastRequests(upstreams []*Upstream) *Upstream { return nil } var best []*Upstream - var bestReqs int = -1 + bestReqs := -1 for _, upstream := range upstreams { if upstream == nil { continue diff --git a/modules/caddyhttp/rewrite/rewrite.go b/modules/caddyhttp/rewrite/rewrite.go index 31ebfb4307e..e51aa3b5548 100644 --- a/modules/caddyhttp/rewrite/rewrite.go +++ b/modules/caddyhttp/rewrite/rewrite.go @@ -377,10 +377,7 @@ func buildQueryString(qs string, repl *caddy.Replacer) string { // performed in normalized/unescaped space. func trimPathPrefix(escapedPath, prefix string) string { var iPath, iPrefix int - for { - if iPath >= len(escapedPath) || iPrefix >= len(prefix) { - break - } + for iPath < len(escapedPath) && iPrefix < len(prefix) { prefixCh := prefix[iPrefix] ch := string(escapedPath[iPath]) diff --git a/modules/caddytls/automation.go b/modules/caddytls/automation.go index 6f3b98a3e10..c9274878a76 100644 --- a/modules/caddytls/automation.go +++ b/modules/caddytls/automation.go @@ -388,10 +388,8 @@ func (ap *AutomationPolicy) onlyInternalIssuer() bool { // isWildcardOrDefault determines if the subjects include any wildcard domains, // or is the "default" policy (i.e. no subjects) which is unbounded. func (ap *AutomationPolicy) isWildcardOrDefault() bool { - isWildcardOrDefault := false - if len(ap.subjects) == 0 { - isWildcardOrDefault = true - } + isWildcardOrDefault := len(ap.subjects) == 0 + for _, sub := range ap.subjects { if strings.HasPrefix(sub, "*") { isWildcardOrDefault = true diff --git a/modules/logging/netwriter.go b/modules/logging/netwriter.go index 7d8481e3c3c..c32bf8de8b2 100644 --- a/modules/logging/netwriter.go +++ b/modules/logging/netwriter.go @@ -202,7 +202,7 @@ func (reconn *redialerConn) Write(b []byte) (n int, err error) { } if n, err = conn2.Write(b); err == nil { if reconn.Conn != nil { - reconn.Conn.Close() + reconn.Close() } reconn.Conn = conn2 } From 61703a147fd63808b13f87b842784235af9759d5 Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Tue, 25 Mar 2025 23:02:55 +0300 Subject: [PATCH 03/10] more lint fixes Signed-off-by: Mohammed Al Sahaf --- caddyconfig/httpcaddyfile/directives.go | 1 + modules/caddyevents/app.go | 1 - modules/caddyhttp/matchers.go | 1 - modules/caddyhttp/rewrite/rewrite.go | 1 - 4 files changed, 1 insertion(+), 3 deletions(-) diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go index 41723333677..6011b85915a 100644 --- a/caddyconfig/httpcaddyfile/directives.go +++ b/caddyconfig/httpcaddyfile/directives.go @@ -178,6 +178,7 @@ func RegisterDirectiveOrder(dir string, position Positional, standardDir string) newOrder = append(newOrder[:i], append([]string{dir}, newOrder[i:]...)...) case After: newOrder = append(newOrder[:i+1], append([]string{dir}, newOrder[i+1:]...)...) + case First, Last: } break } diff --git a/modules/caddyevents/app.go b/modules/caddyevents/app.go index 398c10f1b07..b7dc8f85040 100644 --- a/modules/caddyevents/app.go +++ b/modules/caddyevents/app.go @@ -273,7 +273,6 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) E // implement propagation up the module tree (i.e. start with "a.b.c" then "a.b" then "a" then "") for app.subscriptions[eventName] != nil { - for _, handler := range app.subscriptions[eventName][moduleID] { select { case <-ctx.Done(): diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go index 9dac84b8160..07d692d5d13 100644 --- a/modules/caddyhttp/matchers.go +++ b/modules/caddyhttp/matchers.go @@ -549,7 +549,6 @@ func (MatchPath) matchPatternWithEscapeSequence(escapedPath, matchPath string) b // iPattern and iPath are our cursors/iterator positions for each string var iPattern, iPath int for iPattern < len(matchPath) && iPath < len(escapedPath) { - // get the next character from the request path pathCh := string(escapedPath[iPath]) diff --git a/modules/caddyhttp/rewrite/rewrite.go b/modules/caddyhttp/rewrite/rewrite.go index e51aa3b5548..2b18744db2d 100644 --- a/modules/caddyhttp/rewrite/rewrite.go +++ b/modules/caddyhttp/rewrite/rewrite.go @@ -378,7 +378,6 @@ func buildQueryString(qs string, repl *caddy.Replacer) string { func trimPathPrefix(escapedPath, prefix string) string { var iPath, iPrefix int for iPath < len(escapedPath) && iPrefix < len(prefix) { - prefixCh := prefix[iPrefix] ch := string(escapedPath[iPath]) From d3464efffdc132ef777aee62cffef823c0e86440 Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Tue, 25 Mar 2025 23:09:12 +0300 Subject: [PATCH 04/10] bring back comments to .golangci.yml Signed-off-by: Mohammed Al Sahaf --- .golangci.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 5609f844e6c..db5fc7dd1f3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -59,18 +59,19 @@ linters: rules: - linters: - gosec - text: G115 + text: G115 # TODO: Either we should fix the issues or nuke the linter if it's bad - linters: - gosec - text: G107 + text: G107 # we aren't calling unknown URL - linters: - gosec - text: G203 + text: G203 # as a web server that's expected to handle any template, this is totally in the hands of the user. - linters: - gosec - text: G204 + text: G204 # we're shelling out to known commands, not relying on user-defined input. - linters: - gosec + # the choice of weakrand is deliberate, hence the named import "weakrand" path: modules/caddyhttp/reverseproxy/selectionpolicies.go text: G404 - linters: @@ -102,10 +103,10 @@ formatters: settings: gci: sections: - - standard - - default - - prefix(github.com/caddyserver/caddy/v2/cmd) - - prefix(github.com/caddyserver/caddy) + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - prefix(github.com/caddyserver/caddy/v2/cmd) # ensure that this is always at the top and always has a line break. + - prefix(github.com/caddyserver/caddy) # Custom section: groups all imports with the specified Prefix. custom-order: true exclusions: generated: lax From e42cf4fc80f3accd6b5136a2fefa5facfdd4aa42 Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Tue, 25 Mar 2025 23:19:42 +0300 Subject: [PATCH 05/10] appease the linter some more Signed-off-by: Mohammed Al Sahaf --- listen.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/listen.go b/listen.go index 1a7051bbfd4..4ed0b4c1919 100644 --- a/listen.go +++ b/listen.go @@ -136,7 +136,7 @@ func (fcl *fakeCloseListener) Accept() (net.Conn, error) { } // call underlying accept - conn, err := fcl.sharedListener.Accept() + conn, err := fcl.Accept() if err == nil { // if 0, do nothing, Go's default is already set // and if the connection allows setting KeepAlive, set it @@ -147,7 +147,7 @@ func (fcl *fakeCloseListener) Accept() (net.Conn, error) { err = tconn.SetKeepAlive(false) } if err != nil { - Log().With(zap.String("server", fcl.sharedListener.key)).Warn("unable to set keepalive for new connection:", zap.Error(err)) + Log().With(zap.String("server", fcl.key)).Warn("unable to set keepalive for new connection:", zap.Error(err)) } } return conn, nil @@ -165,7 +165,7 @@ func (fcl *fakeCloseListener) Accept() (net.Conn, error) { // users of this listener, not just our own reference to it; we also don't // do anything with the error because all we could do is log it, but we // explicitly assign it to nothing so we don't forget it's there if needed - _ = fcl.sharedListener.clearDeadline() + _ = fcl.clearDeadline() if netErr, ok := err.(net.Error); ok && netErr.Timeout() { return nil, fakeClosedErr(fcl) @@ -188,8 +188,8 @@ func (fcl *fakeCloseListener) Close() error { // file). But we can set the deadline in the past, // and this is kind of cheating, but it works, and // it apparently even works on Windows. - _ = fcl.sharedListener.setDeadline() - _, _ = listenerPool.Delete(fcl.sharedListener.key) + _ = fcl.setDeadline() + _, _ = listenerPool.Delete(fcl.key) } return nil } @@ -236,7 +236,7 @@ func (sl *sharedListener) setDeadline() error { // Destruct is called by the UsagePool when the listener is // finally not being used anymore. It closes the socket. func (sl *sharedListener) Destruct() error { - return sl.Listener.Close() + return sl.Close() } // fakeClosePacketConn is like fakeCloseListener, but for PacketConns, @@ -279,13 +279,13 @@ func (fcpc *fakeClosePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err e func (fcpc *fakeClosePacketConn) Close() error { if atomic.CompareAndSwapInt32(&fcpc.closed, 0, 1) { _ = fcpc.SetReadDeadline(time.Now()) // unblock ReadFrom() calls to kick old servers out of their loops - _, _ = listenerPool.Delete(fcpc.sharedPacketConn.key) + _, _ = listenerPool.Delete(fcpc.key) } return nil } func (fcpc *fakeClosePacketConn) Unwrap() net.PacketConn { - return fcpc.sharedPacketConn.PacketConn + return fcpc.PacketConn } // sharedPacketConn is like sharedListener, but for net.PacketConns. @@ -296,7 +296,7 @@ type sharedPacketConn struct { // Destruct closes the underlying socket. func (spc *sharedPacketConn) Destruct() error { - return spc.PacketConn.Close() + return spc.Close() } // Unwrap returns the underlying socket From c65fc0bb1a31919a7b849b89256d5bed69fc376a Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Tue, 25 Mar 2025 23:28:55 +0300 Subject: [PATCH 06/10] oops Signed-off-by: Mohammed Al Sahaf --- listen.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/listen.go b/listen.go index 4ed0b4c1919..12ca4b121d3 100644 --- a/listen.go +++ b/listen.go @@ -136,7 +136,7 @@ func (fcl *fakeCloseListener) Accept() (net.Conn, error) { } // call underlying accept - conn, err := fcl.Accept() + conn, err := fcl.sharedListener.Accept() if err == nil { // if 0, do nothing, Go's default is already set // and if the connection allows setting KeepAlive, set it From 57a85ede023aa0012cfb1ba069215b9fc104ba11 Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Thu, 3 Apr 2025 01:50:17 +0300 Subject: [PATCH 07/10] use embedded structs Signed-off-by: Mohammed Al Sahaf --- .golangci.yml | 2 ++ listen.go | 16 ++++++++-------- listeners.go | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index db5fc7dd1f3..cf79557c74c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -42,6 +42,8 @@ linters: - whitespace - zerologlint settings: + staticcheck: + checks: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-QF1008"] # default, and exclude 1 more undesired check errcheck: exclude-functions: - fmt.* diff --git a/listen.go b/listen.go index 12ca4b121d3..1a7051bbfd4 100644 --- a/listen.go +++ b/listen.go @@ -147,7 +147,7 @@ func (fcl *fakeCloseListener) Accept() (net.Conn, error) { err = tconn.SetKeepAlive(false) } if err != nil { - Log().With(zap.String("server", fcl.key)).Warn("unable to set keepalive for new connection:", zap.Error(err)) + Log().With(zap.String("server", fcl.sharedListener.key)).Warn("unable to set keepalive for new connection:", zap.Error(err)) } } return conn, nil @@ -165,7 +165,7 @@ func (fcl *fakeCloseListener) Accept() (net.Conn, error) { // users of this listener, not just our own reference to it; we also don't // do anything with the error because all we could do is log it, but we // explicitly assign it to nothing so we don't forget it's there if needed - _ = fcl.clearDeadline() + _ = fcl.sharedListener.clearDeadline() if netErr, ok := err.(net.Error); ok && netErr.Timeout() { return nil, fakeClosedErr(fcl) @@ -188,8 +188,8 @@ func (fcl *fakeCloseListener) Close() error { // file). But we can set the deadline in the past, // and this is kind of cheating, but it works, and // it apparently even works on Windows. - _ = fcl.setDeadline() - _, _ = listenerPool.Delete(fcl.key) + _ = fcl.sharedListener.setDeadline() + _, _ = listenerPool.Delete(fcl.sharedListener.key) } return nil } @@ -236,7 +236,7 @@ func (sl *sharedListener) setDeadline() error { // Destruct is called by the UsagePool when the listener is // finally not being used anymore. It closes the socket. func (sl *sharedListener) Destruct() error { - return sl.Close() + return sl.Listener.Close() } // fakeClosePacketConn is like fakeCloseListener, but for PacketConns, @@ -279,13 +279,13 @@ func (fcpc *fakeClosePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err e func (fcpc *fakeClosePacketConn) Close() error { if atomic.CompareAndSwapInt32(&fcpc.closed, 0, 1) { _ = fcpc.SetReadDeadline(time.Now()) // unblock ReadFrom() calls to kick old servers out of their loops - _, _ = listenerPool.Delete(fcpc.key) + _, _ = listenerPool.Delete(fcpc.sharedPacketConn.key) } return nil } func (fcpc *fakeClosePacketConn) Unwrap() net.PacketConn { - return fcpc.PacketConn + return fcpc.sharedPacketConn.PacketConn } // sharedPacketConn is like sharedListener, but for net.PacketConns. @@ -296,7 +296,7 @@ type sharedPacketConn struct { // Destruct closes the underlying socket. func (spc *sharedPacketConn) Destruct() error { - return spc.Close() + return spc.PacketConn.Close() } // Unwrap returns the underlying socket diff --git a/listeners.go b/listeners.go index 1a074f6d745..b22df77ba5a 100644 --- a/listeners.go +++ b/listeners.go @@ -574,7 +574,7 @@ type sharedQuicListener struct { // Destruct closes the underlying QUIC listener and its associated net.PacketConn. func (sql *sharedQuicListener) Destruct() error { // close EarlyListener first to stop any operations being done to the net.PacketConn - _ = sql.Close() + _ = sql.EarlyListener.Close() // then close the net.PacketConn return sql.packetConn.Close() } @@ -626,7 +626,7 @@ func (fcql *fakeCloseQuicListener) Accept(_ context.Context) (quic.EarlyConnecti func (fcql *fakeCloseQuicListener) Close() error { if atomic.CompareAndSwapInt32(&fcql.closed, 0, 1) { fcql.contextCancel() - _, _ = listenerPool.Delete(fcql.key) + _, _ = listenerPool.Delete(fcql.sharedQuicListener.key) } return nil } From 3cece4b64439074658c38a24f6b28f9c85b07f98 Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Fri, 2 May 2025 20:56:05 +0300 Subject: [PATCH 08/10] use embedded structs where they were used before Signed-off-by: Mohammed Al Sahaf --- caddyconfig/caddyfile/parse.go | 4 ++-- caddyconfig/httpcaddyfile/builtins.go | 2 +- caddyconfig/httpcaddyfile/directives.go | 6 +++--- cmd/main.go | 2 +- logging.go | 6 +++--- modules/caddyevents/app.go | 2 +- modules/caddyhttp/celmatcher.go | 4 ++-- modules/caddyhttp/headers/caddyfile.go | 2 +- modules/caddyhttp/headers/headers.go | 4 ++-- modules/caddyhttp/push/handler.go | 2 +- modules/caddyhttp/responsewriter.go | 2 +- modules/caddyhttp/reverseproxy/healthchecks.go | 12 ++++++------ modules/caddyhttp/reverseproxy/hosts.go | 4 ++-- modules/caddyhttp/reverseproxy/httptransport.go | 4 ++-- modules/caddyhttp/reverseproxy/reverseproxy.go | 8 ++++---- modules/logging/netwriter.go | 2 +- 16 files changed, 33 insertions(+), 33 deletions(-) diff --git a/caddyconfig/caddyfile/parse.go b/caddyconfig/caddyfile/parse.go index 784e4acd981..d04a1ac4672 100644 --- a/caddyconfig/caddyfile/parse.go +++ b/caddyconfig/caddyfile/parse.go @@ -423,9 +423,9 @@ func (p *parser) doImport(nesting int) error { // make path relative to the file of the _token_ being processed rather // than current working directory (issue #867) and then use glob to get // list of matching filenames - absFile, err := caddy.FastAbs(p.File()) + absFile, err := caddy.FastAbs(p.Dispenser.File()) if err != nil { - return p.Errf("Failed to get absolute path of file: %s: %v", p.File(), err) + return p.Errf("Failed to get absolute path of file: %s: %v", p.Dispenser.File(), err) } var matches []string diff --git a/caddyconfig/httpcaddyfile/builtins.go b/caddyconfig/httpcaddyfile/builtins.go index af481ac4946..3fc08b2c898 100644 --- a/caddyconfig/httpcaddyfile/builtins.go +++ b/caddyconfig/httpcaddyfile/builtins.go @@ -998,7 +998,7 @@ func parseLogHelper(h Helper, globalLogNames map[string]struct{}) ([]ConfigValue cl.WriterRaw = caddyconfig.JSONModuleObject(wo, "output", moduleName, h.warnings) case "sampling": - d := h.NewFromNextSegment() + d := h.Dispenser.NewFromNextSegment() for d.NextArg() { // consume any tokens on the same line, if any. } diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go index 6011b85915a..fd3db9c37ec 100644 --- a/caddyconfig/httpcaddyfile/directives.go +++ b/caddyconfig/httpcaddyfile/directives.go @@ -247,7 +247,7 @@ func (h Helper) MatcherToken() (caddy.ModuleMap, bool, error) { if !h.NextArg() { return nil, false, nil } - return matcherSetFromMatcherToken(h.Token(), h.matcherDefs, h.warnings) + return matcherSetFromMatcherToken(h.Dispenser.Token(), h.matcherDefs, h.warnings) } // ExtractMatcherSet is like MatcherToken, except this is a higher-level @@ -266,9 +266,9 @@ func (h Helper) ExtractMatcherSet() (caddy.ModuleMap, error) { // new dispenser should have been made // solely for this directive's tokens, // with no other uses of same slice - h.Delete() + h.Dispenser.Delete() } - h.Reset() // pretend this lookahead never happened + h.Dispenser.Reset() // pretend this lookahead never happened return matcherSet, nil } diff --git a/cmd/main.go b/cmd/main.go index 80419d4702e..47d702ca7ea 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -302,7 +302,7 @@ type Flags struct { // flag given by name. It panics if the flag is not // in the flag set. func (f Flags) String(name string) string { - return f.Lookup(name).Value.String() + return f.FlagSet.Lookup(name).Value.String() } // Bool returns the boolean representation of the diff --git a/logging.go b/logging.go index fffd576725d..128a54de71b 100644 --- a/logging.go +++ b/logging.go @@ -152,17 +152,17 @@ func (logging *Logging) setupNewDefault(ctx Context) error { } // options for the default logger - options, err := newDefault.buildOptions() + options, err := newDefault.CustomLog.buildOptions() if err != nil { return fmt.Errorf("setting up default log: %v", err) } // set up this new log - err = newDefault.provision(ctx, logging) + err = newDefault.CustomLog.provision(ctx, logging) if err != nil { return fmt.Errorf("setting up default log: %v", err) } - newDefault.logger = zap.New(newDefault.core, options...) + newDefault.logger = zap.New(newDefault.CustomLog.core, options...) // redirect the default caddy logs defaultLoggerMu.Lock() diff --git a/modules/caddyevents/app.go b/modules/caddyevents/app.go index e4559fbdb7d..f88247fda91 100644 --- a/modules/caddyevents/app.go +++ b/modules/caddyevents/app.go @@ -226,7 +226,7 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) c zap.String("origin", originModuleName)) // add event info to replacer, make sure it's in the context - repl, ok := ctx.Value(caddy.ReplacerCtxKey).(*caddy.Replacer) + repl, ok := ctx.Context.Value(caddy.ReplacerCtxKey).(*caddy.Replacer) if !ok { repl = caddy.NewReplacer() ctx.Context = context.WithValue(ctx.Context, caddy.ReplacerCtxKey, repl) diff --git a/modules/caddyhttp/celmatcher.go b/modules/caddyhttp/celmatcher.go index 6d7607c4804..3d118ea798e 100644 --- a/modules/caddyhttp/celmatcher.go +++ b/modules/caddyhttp/celmatcher.go @@ -329,14 +329,14 @@ func (pn celPkixName) ConvertToNative(typeDesc reflect.Type) (any, error) { func (pn celPkixName) ConvertToType(typeVal ref.Type) ref.Val { if typeVal.TypeName() == "string" { - return types.String(pn.String()) + return types.String(pn.Name.String()) } panic("not implemented") } func (pn celPkixName) Equal(other ref.Val) ref.Val { if o, ok := other.Value().(string); ok { - return types.Bool(pn.String() == o) + return types.Bool(pn.Name.String() == o) } return types.ValOrErr(other, "%v is not comparable type", other) } diff --git a/modules/caddyhttp/headers/caddyfile.go b/modules/caddyhttp/headers/caddyfile.go index 2758f290754..f060471b100 100644 --- a/modules/caddyhttp/headers/caddyfile.go +++ b/modules/caddyhttp/headers/caddyfile.go @@ -87,7 +87,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) if err != nil { return nil, h.Err(err.Error()) } - if len(handler.Response.Delete) > 0 { + if len(handler.Response.HeaderOps.Delete) > 0 { handler.Response.Deferred = true } } diff --git a/modules/caddyhttp/headers/headers.go b/modules/caddyhttp/headers/headers.go index 5c160c72e33..ef9e35e7d4d 100644 --- a/modules/caddyhttp/headers/headers.go +++ b/modules/caddyhttp/headers/headers.go @@ -354,9 +354,9 @@ func (rww *responseWriterWrapper) WriteHeader(status int) { if status < 100 || status > 199 { rww.wroteHeader = true } - if rww.require == nil || rww.require.Match(status, rww.Header()) { + if rww.require == nil || rww.require.Match(status, rww.ResponseWriterWrapper.Header()) { if rww.headerOps != nil { - rww.headerOps.ApplyTo(rww.Header(), rww.replacer) + rww.headerOps.ApplyTo(rww.ResponseWriterWrapper.Header(), rww.replacer) } } rww.ResponseWriterWrapper.WriteHeader(status) diff --git a/modules/caddyhttp/push/handler.go b/modules/caddyhttp/push/handler.go index a43e767843b..1fbe53d8366 100644 --- a/modules/caddyhttp/push/handler.go +++ b/modules/caddyhttp/push/handler.go @@ -210,7 +210,7 @@ type linkPusher struct { } func (lp linkPusher) WriteHeader(statusCode int) { - if links, ok := lp.Header()["Link"]; ok { + if links, ok := lp.ResponseWriter.Header()["Link"]; ok { // only initiate these pushes if it hasn't been done yet if val := caddyhttp.GetVar(lp.request.Context(), pushedLink); val == nil { if c := lp.handler.logger.Check(zapcore.DebugLevel, "pushing Link resources"); c != nil { diff --git a/modules/caddyhttp/responsewriter.go b/modules/caddyhttp/responsewriter.go index e9d0e0739ec..904c30c0352 100644 --- a/modules/caddyhttp/responsewriter.go +++ b/modules/caddyhttp/responsewriter.go @@ -158,7 +158,7 @@ func (rr *responseRecorder) WriteHeader(statusCode int) { if rr.shouldBuffer == nil { rr.stream = true } else { - rr.stream = !rr.shouldBuffer(rr.statusCode, rr.Header()) + rr.stream = !rr.shouldBuffer(rr.statusCode, rr.ResponseWriterWrapper.Header()) } // 1xx responses aren't final; just informational diff --git a/modules/caddyhttp/reverseproxy/healthchecks.go b/modules/caddyhttp/reverseproxy/healthchecks.go index 9da3bfefacd..ac42570b2e1 100644 --- a/modules/caddyhttp/reverseproxy/healthchecks.go +++ b/modules/caddyhttp/reverseproxy/healthchecks.go @@ -463,7 +463,7 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, networ markUnhealthy := func() { // increment failures and then check if it has reached the threshold to mark unhealthy - err := upstream.countHealthFail(1) + err := upstream.Host.countHealthFail(1) if err != nil { if c := h.HealthChecks.Active.logger.Check(zapcore.ErrorLevel, "could not count active health failure"); c != nil { c.Write( @@ -473,11 +473,11 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, networ } return } - if upstream.activeHealthFails() >= h.HealthChecks.Active.Fails { + if upstream.Host.activeHealthFails() >= h.HealthChecks.Active.Fails { // dispatch an event that the host newly became unhealthy if upstream.setHealthy(false) { h.events.Emit(h.ctx, "unhealthy", map[string]any{"host": hostAddr}) - upstream.resetHealth() + upstream.Host.resetHealth() } } } @@ -494,13 +494,13 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, networ } return } - if upstream.activeHealthPasses() >= h.HealthChecks.Active.Passes { + if upstream.Host.activeHealthPasses() >= h.HealthChecks.Active.Passes { if upstream.setHealthy(true) { if c := h.HealthChecks.Active.logger.Check(zapcore.InfoLevel, "host is up"); c != nil { c.Write(zap.String("host", hostAddr)) } h.events.Emit(h.ctx, "healthy", map[string]any{"host": hostAddr}) - upstream.resetHealth() + upstream.Host.resetHealth() } } } @@ -596,7 +596,7 @@ func (h *Handler) countFailure(upstream *Upstream) { } // count failure immediately - err := upstream.countFail(1) + err := upstream.Host.countFail(1) if err != nil { if c := h.HealthChecks.Active.logger.Check(zapcore.ErrorLevel, "could not count failure"); c != nil { c.Write( diff --git a/modules/caddyhttp/reverseproxy/hosts.go b/modules/caddyhttp/reverseproxy/hosts.go index bf278f0c7cb..300003f2b87 100644 --- a/modules/caddyhttp/reverseproxy/hosts.go +++ b/modules/caddyhttp/reverseproxy/hosts.go @@ -83,7 +83,7 @@ func (u *Upstream) Available() bool { func (u *Upstream) Healthy() bool { healthy := u.healthy() if healthy && u.healthCheckPolicy != nil { - healthy = u.Fails() < u.healthCheckPolicy.MaxFails + healthy = u.Host.Fails() < u.healthCheckPolicy.MaxFails } if healthy && u.cb != nil { healthy = u.cb.OK() @@ -94,7 +94,7 @@ func (u *Upstream) Healthy() bool { // Full returns true if the remote host // cannot receive more requests at this time. func (u *Upstream) Full() bool { - return u.MaxRequests > 0 && u.NumRequests() >= u.MaxRequests + return u.MaxRequests > 0 && u.Host.NumRequests() >= u.MaxRequests } // fillDialInfo returns a filled DialInfo for upstream u, using the request diff --git a/modules/caddyhttp/reverseproxy/httptransport.go b/modules/caddyhttp/reverseproxy/httptransport.go index d80d5776c9b..23af0b3f935 100644 --- a/modules/caddyhttp/reverseproxy/httptransport.go +++ b/modules/caddyhttp/reverseproxy/httptransport.go @@ -768,7 +768,7 @@ type tcpRWTimeoutConn struct { func (c *tcpRWTimeoutConn) Read(b []byte) (int, error) { if c.readTimeout > 0 { - err := c.SetReadDeadline(time.Now().Add(c.readTimeout)) + err := c.TCPConn.SetReadDeadline(time.Now().Add(c.readTimeout)) if err != nil { if ce := c.logger.Check(zapcore.ErrorLevel, "failed to set read deadline"); ce != nil { ce.Write(zap.Error(err)) @@ -780,7 +780,7 @@ func (c *tcpRWTimeoutConn) Read(b []byte) (int, error) { func (c *tcpRWTimeoutConn) Write(b []byte) (int, error) { if c.writeTimeout > 0 { - err := c.SetWriteDeadline(time.Now().Add(c.writeTimeout)) + err := c.TCPConn.SetWriteDeadline(time.Now().Add(c.writeTimeout)) if err != nil { if ce := c.logger.Check(zapcore.ErrorLevel, "failed to set write deadline"); ce != nil { ce.Write(zap.Error(err)) diff --git a/modules/caddyhttp/reverseproxy/reverseproxy.go b/modules/caddyhttp/reverseproxy/reverseproxy.go index f6eb582615d..88fba55a13f 100644 --- a/modules/caddyhttp/reverseproxy/reverseproxy.go +++ b/modules/caddyhttp/reverseproxy/reverseproxy.go @@ -554,9 +554,9 @@ func (h *Handler) proxyLoopIteration(r *http.Request, origReq *http.Request, w h repl.Set("http.reverse_proxy.upstream.hostport", dialInfo.Address) repl.Set("http.reverse_proxy.upstream.host", dialInfo.Host) repl.Set("http.reverse_proxy.upstream.port", dialInfo.Port) - repl.Set("http.reverse_proxy.upstream.requests", upstream.NumRequests()) + repl.Set("http.reverse_proxy.upstream.requests", upstream.Host.NumRequests()) repl.Set("http.reverse_proxy.upstream.max_requests", upstream.MaxRequests) - repl.Set("http.reverse_proxy.upstream.fails", upstream.Fails()) + repl.Set("http.reverse_proxy.upstream.fails", upstream.Host.Fails()) // mutate request headers according to this upstream; // because we're in a retry loop, we have to copy @@ -827,9 +827,9 @@ func (h Handler) addForwardedHeaders(req *http.Request) error { // (This method is mostly the beginning of what was borrowed from the net/http/httputil package in the // Go standard library which was used as the foundation.) func (h *Handler) reverseProxy(rw http.ResponseWriter, req *http.Request, origReq *http.Request, repl *caddy.Replacer, di DialInfo, next caddyhttp.Handler) error { - _ = di.Upstream.countRequest(1) + _ = di.Upstream.Host.countRequest(1) //nolint:errcheck - defer di.Upstream.countRequest(-1) + defer di.Upstream.Host.countRequest(-1) // point the request to this upstream h.directRequest(req, di) diff --git a/modules/logging/netwriter.go b/modules/logging/netwriter.go index c32bf8de8b2..7d8481e3c3c 100644 --- a/modules/logging/netwriter.go +++ b/modules/logging/netwriter.go @@ -202,7 +202,7 @@ func (reconn *redialerConn) Write(b []byte) (n int, err error) { } if n, err = conn2.Write(b); err == nil { if reconn.Conn != nil { - reconn.Close() + reconn.Conn.Close() } reconn.Conn = conn2 } From 48c5fe144e2d68ff6e5a26d4a61b5d66d8ce538c Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Mon, 2 Jun 2025 20:17:20 +0300 Subject: [PATCH 09/10] disable rule `-QF1006` Signed-off-by: Mohammed Al Sahaf --- .golangci.yml | 2 +- modules/caddyevents/app.go | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index cf79557c74c..0f1082e729b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -43,7 +43,7 @@ linters: - zerologlint settings: staticcheck: - checks: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-QF1008"] # default, and exclude 1 more undesired check + checks: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-QF1006", "-QF1008"] # default, and exclude 1 more undesired check errcheck: exclude-functions: - fmt.* diff --git a/modules/caddyevents/app.go b/modules/caddyevents/app.go index f88247fda91..9fc8fa8ed40 100644 --- a/modules/caddyevents/app.go +++ b/modules/caddyevents/app.go @@ -269,7 +269,11 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) c moduleID := originModuleID // implement propagation up the module tree (i.e. start with "a.b.c" then "a.b" then "a" then "") - for app.subscriptions[eventName] != nil { + for { + if app.subscriptions[eventName] == nil { + break // shortcut if event not bound at all + } + for _, handler := range app.subscriptions[eventName][moduleID] { select { case <-ctx.Done(): From 0459b01b835d3bae96852580d74922b4ca0fa90a Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Mon, 2 Jun 2025 20:25:14 +0300 Subject: [PATCH 10/10] missed a spot Signed-off-by: Mohammed Al Sahaf --- modules/caddyhttp/matchers.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go index 07d692d5d13..48c92f17416 100644 --- a/modules/caddyhttp/matchers.go +++ b/modules/caddyhttp/matchers.go @@ -548,7 +548,10 @@ func (MatchPath) matchPatternWithEscapeSequence(escapedPath, matchPath string) b // increment iPath every time we consume a char from the path; // iPattern and iPath are our cursors/iterator positions for each string var iPattern, iPath int - for iPattern < len(matchPath) && iPath < len(escapedPath) { + for { + if iPattern >= len(matchPath) || iPath >= len(escapedPath) { + break + } // get the next character from the request path pathCh := string(escapedPath[iPath])