🔥 feat: Add response time middleware#3891
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughAdds a ResponseTime middleware that measures per-request handling duration and writes it to a configurable response header. Introduces configuration, implementation, tests, a new exported header constant, and documentation. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client
participant Middleware as ResponseTime
participant App as App Handler (c.Next)
Client->>Middleware: HTTP Request
note right of Middleware `#DDEBF7`: record start = now
Middleware->>Middleware: if cfg.Next(c) == true?
alt skipped
Middleware->>App: call c.Next() (skipped timing)
App-->>Middleware: Response
Middleware-->>Client: Response (no header)
else timed
Middleware->>App: call c.Next()
App-->>Middleware: Response / error
note right of Middleware `#F7F6DD`: elapsed = now - start\nset header cfg.Header = elapsed.String()
Middleware-->>Client: Response with header
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
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. Comment |
Summary of ChangesHello @gaby, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request integrates a new Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3891 +/- ##
==========================================
+ Coverage 91.70% 91.73% +0.03%
==========================================
Files 115 117 +2
Lines 9981 9997 +16
==========================================
+ Hits 9153 9171 +18
+ Misses 528 527 -1
+ Partials 300 299 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a new response time middleware for Fiber that measures request processing duration and exposes it via a configurable response header. The implementation follows the established Fiber middleware patterns with proper configuration support and includes comprehensive documentation.
Key Changes
- Added response time middleware with configurable header name and skip logic
- Implemented table-driven tests covering header formatting, skip logic, and error propagation
- Added
HeaderXResponseTimeconstant to the Fiber constants collection
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
middleware/responsetime/responsetime.go |
Core middleware implementation that measures elapsed time using time.Now() and time.Since() |
middleware/responsetime/config.go |
Configuration structure with Next and Header options, following standard Fiber middleware patterns |
middleware/responsetime/responsetime_test.go |
Table-driven tests for default behavior, skip logic, and error propagation |
middleware/responsetime/config.go |
Config defaults and helper function for applying default values |
constants.go |
Added HeaderXResponseTime constant in alphabetical order |
docs/middleware/responsetime.md |
Complete documentation with examples for default, custom header, and skip configurations |
docs/whats_new.md |
What's new entry describing the middleware functionality |
.github/README.md |
Added middleware to the list with description |
There was a problem hiding this comment.
Code Review
This pull request introduces a new responsetime middleware, which is a valuable addition to Fiber's middleware collection. The implementation is clean, and it comes with comprehensive documentation and a good set of initial tests.
My review has identified one high-severity issue where the documented feature to disable the response header via an empty string is not functional due to the default configuration logic. I've also suggested an improvement to the test suite to cover custom header names, enhancing its completeness.
Overall, this is a solid contribution that will be even better once these points are addressed.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
middleware/responsetime/responsetime_test.go (1)
14-99: Well-structured test coverage.The tests are comprehensive and follow good practices:
- Table-driven design
- Proper use of
t.Parallel()- Covers success, skip, and error paths
- Validates header format by parsing as duration
Optional enhancement: Once the config defaulting issue is resolved, consider adding a test case for explicitly disabling the header:
{ name: "disables header when explicitly set to empty", expectedStatus: fiber.StatusOK, expectHeader: false, explicitEmpty: true, // new flag },Then in the test body:
configs := []Config(nil) if tt.skipWithNext { configs = []Config{{ Next: func(fiber.Ctx) bool { return true }, }} } else if tt.explicitEmpty { configs = []Config{{ Header: "", }} }This would explicitly test that users can opt out of the header.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
.github/README.md(1 hunks)constants.go(1 hunks)docs/middleware/responsetime.md(1 hunks)docs/whats_new.md(1 hunks)middleware/responsetime/config.go(1 hunks)middleware/responsetime/responsetime.go(1 hunks)middleware/responsetime/responsetime_test.go(1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: grivera64
Repo: gofiber/fiber PR: 3807
File: adapter_test.go:118-144
Timestamp: 2025-10-16T07:15:26.529Z
Learning: In Fiber v3, net/http handlers (http.Handler, http.HandlerFunc, or raw func(http.ResponseWriter, *http.Request)) can be passed directly to routing methods like app.Get(), app.Post(), etc. The framework automatically detects and wraps them internally via toFiberHandler/collectHandlers. The github.com/gofiber/fiber/v3/middleware/adaptor package is legacy and should not be suggested for tests or code using native net/http handler support.
Learnt from: sixcolors
Repo: gofiber/fiber PR: 3016
File: middleware/csrf/csrf_test.go:188-193
Timestamp: 2024-09-25T15:57:10.221Z
Learning: In the Fiber framework tests, using `ctx.Response.Header.Cookie` may not be suitable for parsing cookies from the response header, as it requires a `*Cookie` and fills it rather than returning a string value; thus, manual parsing of the `Set-Cookie` header may be necessary.
Learnt from: sixcolors
Repo: gofiber/fiber PR: 3016
File: middleware/csrf/csrf_test.go:188-193
Timestamp: 2024-10-08T19:06:06.583Z
Learning: In the Fiber framework tests, using `ctx.Response.Header.Cookie` may not be suitable for parsing cookies from the response header, as it requires a `*Cookie` and fills it rather than returning a string value; thus, manual parsing of the `Set-Cookie` header may be necessary.
📚 Learning: 2024-09-25T15:57:10.221Z
Learnt from: sixcolors
Repo: gofiber/fiber PR: 3016
File: middleware/csrf/csrf_test.go:188-193
Timestamp: 2024-09-25T15:57:10.221Z
Learning: In the Fiber framework tests, using `ctx.Response.Header.Cookie` may not be suitable for parsing cookies from the response header, as it requires a `*Cookie` and fills it rather than returning a string value; thus, manual parsing of the `Set-Cookie` header may be necessary.
Applied to files:
constants.gomiddleware/responsetime/responsetime_test.go
📚 Learning: 2025-10-16T07:15:26.529Z
Learnt from: grivera64
Repo: gofiber/fiber PR: 3807
File: adapter_test.go:118-144
Timestamp: 2025-10-16T07:15:26.529Z
Learning: In Fiber v3, net/http handlers (http.Handler, http.HandlerFunc, or raw func(http.ResponseWriter, *http.Request)) can be passed directly to routing methods like app.Get(), app.Post(), etc. The framework automatically detects and wraps them internally via toFiberHandler/collectHandlers. The github.com/gofiber/fiber/v3/middleware/adaptor package is legacy and should not be suggested for tests or code using native net/http handler support.
Applied to files:
.github/README.md
📚 Learning: 2024-09-25T16:17:00.969Z
Learnt from: sixcolors
Repo: gofiber/fiber PR: 3016
File: middleware/session/config.go:16-26
Timestamp: 2024-09-25T16:17:00.969Z
Learning: In the session middleware `Config` struct, `Store` is backed by `fiber.Storage`; they are different entities serving distinct purposes in session management.
Applied to files:
.github/README.md
📚 Learning: 2024-11-10T23:44:13.704Z
Learnt from: gaby
Repo: gofiber/fiber PR: 3193
File: middleware/adaptor/adaptor.go:111-111
Timestamp: 2024-11-10T23:44:13.704Z
Learning: In the `middleware/adaptor/adaptor.go` file of the Fiber framework, when updating context handling, replacing `c.Context()` with `c.RequestCtx()` is appropriate to access the `fasthttp.RequestCtx`.
Applied to files:
.github/README.mdmiddleware/responsetime/responsetime.go
📚 Learning: 2024-06-30T00:38:06.580Z
Learnt from: sixcolors
Repo: gofiber/fiber PR: 3051
File: middleware/session/session.go:215-216
Timestamp: 2024-06-30T00:38:06.580Z
Learning: Parallel tests for `Session.Save` already exist in the `middleware/session/session_test.go` file, specifically in the `Test_Session_Save` and `Test_Session_Save_Expiration` functions.
Applied to files:
middleware/responsetime/responsetime_test.go
📚 Learning: 2025-10-16T07:19:52.418Z
Learnt from: grivera64
Repo: gofiber/fiber PR: 3807
File: adapter_test.go:118-144
Timestamp: 2025-10-16T07:19:52.418Z
Learning: In the Fiber codebase, the linter does not allow `require` assertions from within HTTP handlers (including net/http-style handlers). Use `t.Fatalf`, `t.Errorf`, or similar `testing.T` methods for error handling inside handler functions instead.
Applied to files:
middleware/responsetime/responsetime_test.go
📚 Learning: 2024-10-12T10:01:44.206Z
Learnt from: sixcolors
Repo: gofiber/fiber PR: 3016
File: middleware/session/middleware_test.go:190-191
Timestamp: 2024-10-12T10:01:44.206Z
Learning: When testing session `IdleTimeout` expiration, it's acceptable to use `time.Sleep` to simulate the passage of time in tests.
Applied to files:
middleware/responsetime/responsetime_test.go
📚 Learning: 2024-10-08T19:06:06.583Z
Learnt from: sixcolors
Repo: gofiber/fiber PR: 2922
File: middleware/cors/utils.go:63-71
Timestamp: 2024-10-08T19:06:06.583Z
Learning: The project uses the testify/assert package for assertions in unit tests.
Applied to files:
middleware/responsetime/responsetime_test.go
🧬 Code graph analysis (3)
middleware/responsetime/config.go (1)
constants.go (1)
HeaderXResponseTime(283-283)
middleware/responsetime/responsetime_test.go (4)
middleware/responsetime/responsetime.go (1)
New(10-31)constants.go (4)
StatusOK(52-52)StatusTeapot(91-91)MethodGet(5-5)HeaderXResponseTime(283-283)middleware/responsetime/config.go (1)
Config(8-18)app.go (1)
ErrorHandler(59-59)
middleware/responsetime/responsetime.go (2)
middleware/responsetime/config.go (1)
Config(8-18)ctx_interface_gen.go (1)
Ctx(18-432)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Agent
- GitHub Check: lint
- GitHub Check: unit (1.25.x, windows-latest)
- GitHub Check: unit (1.25.x, macos-latest)
- GitHub Check: repeated
- GitHub Check: Compare
🔇 Additional comments (5)
.github/README.md (1)
757-757: LGTM!The middleware table entry is well-formatted and accurately describes the new responsetime middleware functionality.
constants.go (1)
283-283: LGTM!The new header constant follows the existing naming conventions and is properly placed within the HTTP Headers section.
docs/middleware/responsetime.md (1)
1-55: Documentation looks good overall.The documentation is comprehensive and follows Fiber's conventions. However, please verify that line 55's claim about disabling the header by leaving it empty is consistent with the actual implementation (see my comment on config.go).
docs/whats_new.md (1)
1247-1252: Documentation is clear and well-written.The description accurately explains the middleware's purpose and configuration. However, please ensure the claim about disabling headers by setting
Headerto an empty string is consistent with the implementation (see my comment on config.go).middleware/responsetime/responsetime.go (1)
9-31: Implementation logic is correct.The middleware correctly:
- Skips execution when
Nextreturns true- Measures elapsed time around
c.Next()- Only sets the header when
cfg.Headeris non-empty- Properly propagates errors from downstream handlers
The logic to allow disabling the header (line 25) is correct, but the config defaulting bug in
config.goprevents users from actually setting an empty header. Once that's fixed, this implementation will work as intended.
Summary
Based on: https://expressjs.com/en/resources/middleware/response-time.html