Skip to content

Conversation

@vearne
Copy link
Owner

@vearne vearne commented Sep 29, 2025

Summary by CodeRabbit

  • New Features

    • Added options to configure error HTTP status, default message, content type, and callback hooks (including Gin context).
  • Refactor

    • Improved timeout response handling for more consistent header propagation; no breaking changes.
  • Chores

    • Upgraded Go toolchain to 1.24 and updated numerous dependencies.
    • Updated linting configuration and CI tooling to newer versions and adjusted lint exclusions.

@coderabbitai
Copy link

coderabbitai bot commented Sep 29, 2025

Walkthrough

Updates CI and linter configs, upgrades Go to 1.24 and many dependencies, adds new public option constructors in the timeout package, refactors timeout header propagation via a copy helper and composite literal initialization, and performs minor import/order cleanups and test import adjustments.

Changes

Cohort / File(s) Summary
CI workflow updates
.github/workflows/golang-ci.yml
Bumps Go setup from 1.22 to 1.24 and updates golangci-lint image to v2.4.0; adds env GOLANGCI_LINT_RUN_BUILDVCS: false.
Lint configuration overhaul
.golangci.yml
Restructures linter config: replaces previous enable/disable layout with default: none plus enabled list, moves govet settings under settings.govet, and replaces issues exclusions with new exclusions and formatters.exclusions blocks.
Dependencies and toolchain
go.mod
Upgrades module/toolchain to Go 1.24.0 (toolchain go1.24.6) and updates numerous direct and indirect dependencies (e.g., gin v1.11.0, testify v1.11.1, sonic, quic-go components, goccy/go-yaml, x/* modules).
Timeout package: new options
options.go
Adds public Option constructors: WithErrorHttpCode, WithDefaultMsg, WithContentType, WithCallBack, WithGinCtxCallBack; consolidates/imports github.com/gin-gonic/gin.
Timeout package: response import reorder
response.go
Reorders imports (moves net/http position) with no behavioral changes.
Timeout package: header copy refactor
timeout.go
Initializes TimeoutWriter via composite literal, replaces manual header-copy loop with new helper copyHeaders(dst, src http.Header), and adjusts imports (adds gin, buffpool).
Tests
timeout_test.go
Adds/reorders test imports (github.com/gin-gonic/gin, github.com/stretchr/testify) with no test logic changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Client
  participant G as Gin Router
  participant T as Timeout Middleware
  participant H as Handler

  C->>G: HTTP Request
  G->>T: Invoke middleware
  rect rgb(240,248,255)
    note right of T: Apply options (error code, default msg, content-type, callbacks)
    T->>H: Forward request
    alt handler completes before timeout
      H-->>T: Response (status, headers, body)
      T->>T: copyHeaders(dst, src)
      T-->>G: Write status/headers/body
      T->>T: invoke CallBack/GinCtxCallBack (if set)
    else timeout occurs
      T->>T: Prepare default timeout response
      T-->>G: Write timeout status/headers/body
      T->>T: invoke CallBack/GinCtxCallBack (if set)
    end
  end
  G-->>C: HTTP Response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

In burrows of code where timeouts tick,
I thump my paw—make headers stick.
New options bloom like clover bright,
Middleware hums through day and night.
Linter nods, the build takes flight—🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The title mentions upgrading golangci-lint and generic code optimizations, but it doesn’t clearly capture the primary changes in dependency and module version bumps or the new public option constructors and helper functions introduced in this PR. It is overly vague in describing the code improvements portion and does not effectively convey the scope of the changes. Please revise the title to succinctly highlight the most significant changes, for example by specifying the Go toolchain and golangci-lint version updates along with key code enhancements like the new timeout header copy helper and option constructors.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/lint

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b9b2950 and 595816f.

📒 Files selected for processing (1)
  • .github/workflows/golang-ci.yml (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/golang-ci.yml

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
timeout.go (1)

95-99: Bug: setting Content-Type after WriteHeader loses the header on real servers.

net/http sends headers when WriteHeader is called; setting headers afterward has no effect. Move the header set before WriteHeader.

-            tw.ResponseWriter.WriteHeader(tw.Response.GetCode(&cp))
-
-            tw.ResponseWriter.Header().Set("Content-Type", tw.Response.GetContentType(&cp))
-            n, err = tw.ResponseWriter.Write(encodeBytes(tw.Response.GetContent(&cp)))
+            // set headers first
+            tw.ResponseWriter.Header().Set("Content-Type", tw.Response.GetContentType(&cp))
+            // then write status and body
+            tw.ResponseWriter.WriteHeader(tw.Response.GetCode(&cp))
+            n, err = tw.ResponseWriter.Write(encodeBytes(tw.Response.GetContent(&cp)))
options.go (1)

28-53: Avoid mutating the shared default response

Each of the new option helpers assigns defaultResponse directly to t.Response before mutating it. Because defaultResponse is the global fallback instance, calling SetCode/SetContent/SetContentType here changes the shared object, so later middleware instances (even those that never opted in) inherit the mutated code/content. Under load, concurrent requests can race on the same instance and leak one user’s timeout payload into another’s response. Please make sure these setters operate on a fresh copy—e.g. clone or instantiate a new default response per writer—before applying user overrides.

🧹 Nitpick comments (5)
.github/workflows/golang-ci.yml (2)

26-26: Pin to patch and fetch latest 1.24 automatically.

Use 1.24.x with check-latest to keep CI on the latest security patch.

-          go-version: 1.24
+          go-version: 1.24.x
+          check-latest: true

Also consider actions/setup-go@v5 for built‑in caching.


35-35: Good upgrade; consider aligning module mode and adding a version check.

  • Lint runs with modules-download-mode=mod while tests use vendor. Aligning these avoids “works in one job, fails in another.”
  • Add a quick version step to surface the linter version in logs.
    - name: golangci-lint version
      run: golangci-lint --version

Optionally switch lint to vendor mode if you intend to keep vendor in CI.

timeout.go (2)

118-119: Header copy semantics: avoid slice aliasing and ensure canonical behavior.

Assigning slices (dst[k] = vv) aliases backing arrays and may overwrite pre‑set multi‑value headers unexpectedly. Prefer Del+Add or clone values.

-            copyHeaders(tw.ResponseWriter.Header(), tw.Header())
+            copyHeaders(tw.ResponseWriter.Header(), tw.Header())

And update copyHeaders below:

-func copyHeaders(dst, src http.Header) {
-    for k, vv := range src {
-        dst[k] = vv
-    }
-}
+func copyHeaders(dst, src http.Header) {
+    for k, vv := range src {
+        dst.Del(k)
+        for _, v := range vv {
+            dst.Add(k, v)
+        }
+    }
+}

109-111: Which context should callbacks see?

You invoke GinCtxCallBack with the original c (already Aborted), not the cp passed through the remaining handlers. Confirm this is intentional; some users may expect request-scoped values set by later handlers.

If you want callbacks to observe the handler-modified context, pass &cp instead.

-            if tw.GinCtxCallBack != nil {
-                tw.GinCtxCallBack(c)
-            }
+            if tw.GinCtxCallBack != nil {
+                tw.GinCtxCallBack(&cp)
+            }
.golangci.yml (1)

24-29: Path exclusions: minor cleanup.

You exclude both example and examples$. Consider consolidating to a single regex (e.g., ^examples?$) to avoid drift.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a2f7dc1 and b9b2950.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • .github/workflows/golang-ci.yml (2 hunks)
  • .golangci.yml (1 hunks)
  • go.mod (1 hunks)
  • options.go (5 hunks)
  • response.go (1 hunks)
  • timeout.go (4 hunks)
  • timeout_test.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
timeout.go (2)
writer.go (1)
  • TimeoutWriter (11-24)
options.go (1)
  • TimeoutOptions (13-18)
options.go (1)
writer.go (1)
  • TimeoutWriter (11-24)
🔇 Additional comments (3)
response.go (1)

5-5: Import reshuffle only — LGTM.

timeout_test.go (1)

5-6: Test imports update — LGTM.

.golangci.yml (1)

1-1: Approve .golangci.yml v2 config — keys match v2.4.0 spec
All linters.*, linters.settings.govet.*, exclusions.*, and formatters.exclusions.* keys align with the official golangci-lint v2.4.0 documentation.

@vearne vearne merged commit 22bd61c into master Sep 29, 2025
2 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants