Skip to content

fix(middlewares): cache preset HTTP client; share TransportFactory in slack fallback#642

Merged
CybotTM merged 1 commit into
mainfrom
fix/issue-630
May 14, 2026
Merged

fix(middlewares): cache preset HTTP client; share TransportFactory in slack fallback#642
CybotTM merged 1 commit into
mainfrom
fix/issue-630

Conversation

@CybotTM

@CybotTM CybotTM commented May 13, 2026

Copy link
Copy Markdown
Member

Summary

Two defense-in-depth follow-ups from #624 tracked in #630.

  • A. PresetLoader now caches a single *http.Client (constructed in NewPresetLoader from TransportFactory()) instead of building a fresh client and *http.Transport on every loadFromURL call. Bursty preset fetches now share the underlying connection pool / idle-conn reuse.
  • B. The deprecated Slack middleware (middlewares/slack.go) routes its fallback *http.Client through TransportFactory() instead of inheriting http.DefaultTransport. Both construction sites — NewSlack (line 51) and the nil-guard in pushMessage (line 94) — are updated.

Caveats

  • Test ordering constraint: Caching the client means SetTransportFactoryForTest only takes effect on the cached client when called BEFORE NewPresetLoader. Replacing the factory after construction has no effect. This is now documented on NewPresetLoader's godoc and on the PresetLoader.httpClient field. The existing regression test TestPresetLoader_LoadFromURL_UsesTransportFactory already follows this ordering, so it remains green.
  • Slack middleware is deprecated in favour of the generic webhook system with the slack preset. The change in slack.go is explicitly defense-in-depth for the deprecation window — operators are still using it, and inheriting http.DefaultTransport while the rest of the webhook stack converges on TransportFactory() is the kind of latent posture drift this codebase has been actively closing.

TDD

Both tests written first and verified failing (compile error: undefined field), then made to pass:

  • TestPresetLoader_ClientReused (new file middlewares/preset_client_cache_test.go) — installs a counting SetTransportFactoryForTest BEFORE NewPresetLoader, performs two loadFromURL calls, asserts the factory was invoked exactly once, and pointer-checks that loader.httpClient is the same instance across calls.
  • TestSlack_FallbackClient_UsesTransportFactory (appended to middlewares/slack_test.go) — installs a sentinel *http.Transport via SetTransportFactoryForTest and asserts NewSlack(...).Client.Transport is the same pointer.

Test plan

  • go test ./middlewares/... -count=1 -short — passes (10.6s)
  • golangci-lint run ./... — 0 issues
  • New tests fail before implementation (compile error referencing the cached field), pass after
  • Existing TestPresetLoader_LoadFromURL_UsesTransportFactory still green (it already installs the factory before NewPresetLoader)
  • Mutation-test suites (preset_mutation_test.go, webhook_mutation_test.go, slack_mutation_test.go) included in the full middlewares run
  • CI green

Closes #630

…ugh TransportFactory

Two defense-in-depth follow-ups from #624 surfaced in #630.

A. PresetLoader now caches a single *http.Client constructed in
   NewPresetLoader from TransportFactory(), instead of building a fresh
   client (and a fresh *http.Transport with its own connection pool) on
   every loadFromURL call. Bursty preset fetches now share idle-conn
   reuse. Test ordering constraint: SetTransportFactoryForTest must run
   BEFORE NewPresetLoader to influence the cached client; this is
   documented on the constructor's godoc.

B. Slack middleware (deprecated) now routes its fallback *http.Client
   through TransportFactory() instead of inheriting http.DefaultTransport.
   Both construction sites in slack.go (NewSlack and the nil-guard in
   pushMessage) are updated for consistency.

Tests added (TDD, both initially failing):
- TestPresetLoader_ClientReused: counts factory invocations across two
  loadFromURL calls and asserts pointer-identity of loader.httpClient.
- TestSlack_FallbackClient_UsesTransportFactory: installs a sentinel
  transport via SetTransportFactoryForTest and asserts NewSlack wires it
  through to m.Client.Transport.

Closes #630

Signed-off-by: Sebastian Mendel <[email protected]>
Copilot AI review requested due to automatic review settings May 13, 2026 21:49
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests labels May 13, 2026
@sonarqubecloud

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval for maintainer PR

All automated quality gates passed. See SECURITY_CONTROLS.md for compensating controls.

@github-actions

Copy link
Copy Markdown

✅ Mutation Testing Results

Mutation Score: 100.00% (threshold: 60%)

✨ Good job! Mutation score meets the threshold.

What is mutation testing?

Mutation testing measures test quality by introducing small changes (mutations) to the code and checking if tests detect them. A higher score means better test effectiveness.

  • Killed mutants: Tests caught the mutation (good!)
  • Survived mutants: Tests missed the mutation (needs improvement)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Defense-in-depth follow-ups to PR #624: cache the HTTP client in PresetLoader for connection reuse, and route the deprecated Slack middleware's fallback client through the shared TransportFactory() for consistent TLS/proxy posture.

Changes:

  • Cache a single *http.Client on PresetLoader, constructed once in NewPresetLoader from TransportFactory().
  • Wire Slack's fallback *http.Client (both in NewSlack and the nil-guard in pushMessage) through TransportFactory().
  • Add regression tests for client reuse and Slack transport wiring; document changes in CHANGELOG.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
middlewares/preset.go Adds cached httpClient field and uses it in loadFromURL.
middlewares/slack.go Routes fallback HTTP clients through TransportFactory().
middlewares/preset_client_cache_test.go New regression test asserting client/transport reuse.
middlewares/slack_test.go New regression test for Slack fallback transport wiring.
CHANGELOG.md Documents the change under Unreleased.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request optimizes the PresetLoader by caching a single *http.Client initialized via TransportFactory(), which enables connection pooling and improves performance for remote preset fetches. Additionally, the deprecated Slack middleware has been updated to use TransportFactory() for its fallback HTTP client to ensure consistent TLS and proxy settings. New regression tests were introduced to verify these changes. I have no feedback to provide as there were no review comments to assess.

@codecov

codecov Bot commented May 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.86%. Comparing base (c60cd65) to head (e0417f3).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #642   +/-   ##
=======================================
  Coverage   87.86%   87.86%           
=======================================
  Files          88       88           
  Lines       10898    10898           
=======================================
  Hits         9576     9576           
  Misses       1081     1081           
  Partials      241      241           
Flag Coverage Δ
integration 87.85% <100.00%> (-0.02%) ⬇️
unittests 84.90% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@CybotTM CybotTM added this pull request to the merge queue May 14, 2026
Merged via the queue into main with commit a170de4 May 14, 2026
31 checks passed
@CybotTM CybotTM deleted the fix/issue-630 branch May 14, 2026 05:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cache *http.Client on PresetLoader; share TransportFactory in slack.go

2 participants