Skip to content

Conversation

PolyAnthi
Copy link

@PolyAnthi PolyAnthi commented Sep 1, 2025

Description

The caching middleware inside of GoFiber has an option called "CacheControl". By default, this is set to false. However, it is never actually enforced and browsers with "No-Cache" as its cache control header will still bypass (when on false). This PR fixes that.

Changes introduced

List the new features or adjustments introduced in this pull request. Provide details on benchmarks, documentation updates, changelog entries, and if applicable, the migration guide.

  • Changelog/What's New: Fixed CacheControl config in cache middleware being ignored.

Type of change

  • Enhancement (improvement to existing features and functionality)

Checklist

  • Followed the inspiration of the Express.js framework for new functionalities, making them similar in usage.
  • Conducted a self-review of the code and provided comments for complex or critical parts.
  • Updated the documentation in the /docs/ directory for Fiber's documentation.
  • Added or updated unit tests to validate the effectiveness of the changes or new features.
  • Ensured that new and existing unit tests pass locally with the changes.
  • Verified that any new dependencies are essential and have been agreed upon by the maintainers/community.
  • Aimed for optimal performance with minimal allocations in the new code.
  • Provided benchmarks for the new code to analyze and improve upon.

Commit formatting

Please use emojis in commit messages for an easy way to identify the purpose or intention of a commit. Check out the emoji cheatsheet here: CONTRIBUTING.md

@PolyAnthi PolyAnthi requested a review from a team as a code owner September 1, 2025 23:55
Copy link

welcome bot commented Sep 1, 2025

Thanks for opening this pull request! 🎉 Please check out our contributing guidelines. If you need help or want to chat with us, join us on Discord https://gofiber.io/discord

Copy link
Contributor

coderabbitai bot commented Sep 1, 2025

Note

Other AI code review bot(s) detected

CodeRabbit 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.

Warning

Rate limit exceeded

@PolyAnthi has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 7 minutes and 26 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 3028c8c and a77ef7a.

📒 Files selected for processing (1)
  • middleware/cache/cache_test.go (7 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

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

Choose a reason for hiding this comment

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

Summary of Changes

Hello @PolyAnthi, 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 addresses a critical bug within the GoFiber caching middleware. The core issue was that the CacheControl configuration, intended to manage how caching interacts with browser No-Cache directives, was not being properly applied. This fix ensures that the middleware now correctly respects the CacheControl setting, preventing unintended cache bypasses and improving the reliability of the caching mechanism.

Highlights

  • CacheControl Configuration Fix: Resolved an issue in the GoFiber caching middleware where the "CacheControl" configuration option was being ignored. Previously, browsers sending a "No-Cache" header could bypass caching even when "CacheControl" was set to false, which was unintended. The fix ensures that this setting is now correctly enforced.
Using Gemini Code Assist

The 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 in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

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

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 correctly addresses an issue where the CacheControl configuration was being ignored by the middleware. The change ensures that the Cache-Control: no-cache request header is only respected when cfg.CacheControl is explicitly set to true.

I have one suggestion with medium severity to improve the readability of the conditional logic.

More importantly, there is a high severity issue regarding testing. It appears this change will cause the existing test Test_Cache_WithNoCacheRequestDirective to fail, as it asserts behavior that is now correctly fixed. This test needs to be updated to reflect the new, correct behavior (i.e., expect a cache hit when CacheControl is false and a no-cache header is present). It would also be beneficial to add a new test case to verify that the no-cache directive is still respected when CacheControl is set to true to ensure full coverage of this feature.

PolyAnthi and others added 2 commits September 2, 2025 00:58
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@PolyAnthi
Copy link
Author

I believe the solution there with converting one to deal with CacheControl: false and one to use the config with CacheControl: true is appropriate here.

@PolyAnthi
Copy link
Author

/gemini summary

Copy link
Contributor

Summary of Changes

This pull request addresses a critical bug in GoFiber's caching middleware where the CacheControl configuration was being ignored, leading to unintended cache bypasses for requests with a "No-Cache" header. The changes ensure that the CacheControl setting is properly enforced. Additionally, the PR includes a comprehensive refactoring of the cache middleware's test suite, improving its maintainability and reliability.

Highlights

  • Corrected CacheControl Logic: The caching middleware now correctly respects the cfg.CacheControl option. Previously, requests with a "No-Cache" header would bypass the cache even when CacheControl was set to false. This is fixed by ensuring the cache is bypassed only if CacheControl is enabled AND a no-cache directive is present.
  • Test Suite Refactoring: The test suite for the cache middleware has undergone significant refactoring, including updating import paths, standardizing assertion methods to utils.AssertEqual, and streamlining test handlers for better clarity and robustness.
Changelog
  • middleware/cache/cache.go
    • Modified the cache hit condition to correctly evaluate cfg.CacheControl alongside the noCache request directive, ensuring proper cache bypass behavior.
  • middleware/cache/cache_test.go
    • Updated Go module import paths from fiber/v3 to fiber/v2 and utils/v2 to utils.
    • Replaced require.NoError and require.Equal assertions with utils.AssertEqual for consistency.
    • Adjusted various test handlers to use c.Query() or time.Now().UnixNano() for more dynamic and reliable test data generation.
    • Removed several outdated or redundant test cases related to cache invalidation, uncacheable status codes, cache age headers, and specific cache control directives, simplifying the test suite.
    • Explicitly configured CacheControl: true in Test_Cache_WithETagAndNoCacheRequestDirective to properly test the intended behavior.
Activity
  • welcome[bot] provided a standard welcome message.
  • coderabbitai[bot] initiated an AI review, providing a detailed walkthrough, summary of changes, sequence diagram, related PRs, and suggested labels/reviewers. It also noted the presence of other AI review bots.
  • PolyAnthi (author) confirmed the chosen solution approach for handling CacheControl configurations.
  • gemini-code-assist[bot] suggested a more readable logical grouping for a boolean condition in middleware/cache/cache.go, which was adopted in the patch.

Copy link
Contributor

@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: 3

🧹 Nitpick comments (1)
middleware/cache/cache_test.go (1)

686-699: Add a direct no-ETag test for no-cache when CacheControl=true.

You cover the ETag path well. A small additional test ensures we also respect no-cache without ETag.

+func Test_Cache_WithNoCacheRequestDirective_RespectWhenEnabled(t *testing.T) {
+	t.Parallel()
+	app := fiber.New()
+	app.Use(New(Config{CacheControl: true}))
+	app.Get("/", func(c *fiber.Ctx) error {
+		return c.SendString(c.Query("id", "1"))
+	})
+	// Seed cache with id=1
+	_, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
+	utils.AssertEqual(t, nil, err)
+	// no-cache should bypass cache and fetch fresh
+	req := httptest.NewRequest(fiber.MethodGet, "/?id=2", nil)
+	req.Header.Set(fiber.HeaderCacheControl, noCache)
+	resp, err := app.Test(req)
+	utils.AssertEqual(t, nil, err)
+	body, err := io.ReadAll(resp.Body)
+	utils.AssertEqual(t, nil, err)
+	utils.AssertEqual(t, cacheMiss, resp.Header.Get("X-Cache"))
+	utils.AssertEqual(t, []byte("2"), body)
+}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a7556f9 and 3028c8c.

📒 Files selected for processing (1)
  • middleware/cache/cache_test.go (26 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Format Go code using gofumpt (enforced via make format)
Ensure code passes golangci-lint checks (enforced via make lint)
Optimize struct field alignment using betteralign (enforced via make betteralign)
Modernize Go code using gopls modernize (enforced via make modernize)

Files:

  • middleware/cache/cache_test.go
🧠 Learnings (5)
📚 Learning: 2024-11-15T07:56:21.623Z
Learnt from: ReneWerner87
PR: gofiber/fiber#3161
File: app.go:923-932
Timestamp: 2024-11-15T07:56:21.623Z
Learning: In the Fiber framework, breaking changes are acceptable when moving from version 2 to version 3, including modifications to method signatures such as in the `Test` method in `app.go`.

Applied to files:

  • middleware/cache/cache_test.go
📚 Learning: 2024-10-02T23:03:31.727Z
Learnt from: sixcolors
PR: gofiber/fiber#3016
File: middleware/session/store.go:164-167
Timestamp: 2024-10-02T23:03:31.727Z
Learning: Unit tests in this project use testify require.

Applied to files:

  • middleware/cache/cache_test.go
📚 Learning: 2024-10-08T19:06:06.583Z
Learnt from: sixcolors
PR: gofiber/fiber#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/cache/cache_test.go
📚 Learning: 2024-11-10T23:44:13.704Z
Learnt from: gaby
PR: gofiber/fiber#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:

  • middleware/cache/cache_test.go
📚 Learning: 2024-09-25T15:57:10.221Z
Learnt from: sixcolors
PR: gofiber/fiber#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:

  • middleware/cache/cache_test.go
🧬 Code graph analysis (1)
middleware/cache/cache_test.go (4)
ctx_interface_gen.go (1)
  • Ctx (17-414)
middleware/cache/cache.go (1)
  • New (68-302)
middleware/cache/config.go (1)
  • Config (11-75)
req.go (2)
  • Query (726-733)
  • Params (611-617)
🔇 Additional comments (5)
middleware/cache/cache_test.go (5)

34-44: LGTM: verifies Cache-Control header emission when CacheControl=true.

Asserting "public, max-age=10" on the second request correctly exercises the cache-hit path with CacheControl enabled.


118-174: Good coverage: confirms no-cache is ignored when CacheControl=false (the bug fix).

Requests with "Cache-Control: no-cache" still return a cache hit and the original payload, matching the intended behavior when CacheControl is disabled.


186-239: ETag + no-cache behavior validated end-to-end with CacheControl=true.

Nice sequence covering 200 vs 304 and cache miss vs hit—this guards against regressions in the interaction between ETag and cache-control directives.


249-261: ** no-store request directive correctly bypasses cache.**

This ensures the middleware unconditionally skips caching when clients send no-store.


269-297: Defaults are correct – no changes needed
ConfigDefault explicitly sets CacheControl: false and configDefault preserves the zero‐value when not overridden, so tests remain valid.

@PolyAnthi
Copy link
Author

Appears I was updating my, local, V2 copy of middleware and pushed that. I have amended this to the V3 copy from the repo

@gaby gaby added the v3 label Sep 2, 2025
@gaby gaby added this to v3 Sep 2, 2025
@gaby gaby added this to the v3 milestone Sep 2, 2025
@gaby gaby moved this to In Progress in v3 Sep 2, 2025
@gaby gaby changed the title 🩹 fix: cfg.CacheControl being ignored 🐛 bug: Fix cfg.CacheControl being ignored Sep 2, 2025
Copy link

codecov bot commented Sep 2, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.03%. Comparing base (e83a762) to head (a77ef7a).
⚠️ Report is 15 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3726      +/-   ##
==========================================
- Coverage   92.08%   92.03%   -0.06%     
==========================================
  Files         115      115              
  Lines       11535    11535              
==========================================
- Hits        10622    10616       -6     
- Misses        662      667       +5     
- Partials      251      252       +1     
Flag Coverage Δ
unittests 92.03% <100.00%> (-0.06%) ⬇️

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.

@gaby
Copy link
Member

gaby commented Sep 2, 2025

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

Codex Review: Here are some suggestions.

Reply with @codex fix comments to fix any unresolved comments.

About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you open a pull request for review, mark a draft as ready, or comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex fix this CI failure" or "@codex address that feedback".

Comment on lines 147 to +150
_, size := heap.remove(e.heapidx)
storedBytes -= size
}
} else if e.exp != 0 && !hasRequestDirective(c, noCache) {
} else if e.exp != 0 && !(cfg.CacheControl && hasRequestDirective(c, noCache)) {

Choose a reason for hiding this comment

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

[P1] Honor client no-cache regardless of CacheControl flag

The new condition !(cfg.CacheControl && hasRequestDirective(c, noCache)) now serves cached entries whenever CacheControl is left at its default false, even if the client explicitly sends Cache-Control: no-cache. With this change there is no longer a way for clients to force a refresh of a still‑valid entry (e.g. when Expiration is long or zero) unless the application also enables CacheControl, which was previously only responsible for emitting response headers. Existing deployments that rely on no-cache requests to bypass server-side caching will now receive stale data until the entry expires or is manually invalidated. Consider keeping the bypass behavior independent from the response header option or providing a dedicated switch for it.

Useful? React with 👍 / 👎.

Copy link
Member

Choose a reason for hiding this comment

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

👍

@ReneWerner87
Copy link
Member

The caching middleware inside of GoFiber has an option called "CacheControl". By default, this is set to false. However, it is never actually enforced and browsers with "No-Cache" as its cache control header will still bypass (when on false). This PR fixes that.

I checked the code.
The configuration for cacheControl currently only controls the response header for the client.

Perhaps this should be better documented in the configuration.

This configuration should not be used to control caching; this is controlled by setting the middleware itself.

The no-cache parameter in the request header should always be considered, because it is a clear instruction from the client to the server.

Or is the idea to prevent the cache from being controlled on the client side?
WDYT @gaby

@gaby
Copy link
Member

gaby commented Sep 10, 2025

@ReneWerner87 Agree on your statement. The no-cache from the user should take precedence.

Reject this PR

@gaby
Copy link
Member

gaby commented Sep 12, 2025

Closing in favor of #3740

@gaby gaby closed this Sep 12, 2025
@github-project-automation github-project-automation bot moved this from In Progress to Done in v3 Sep 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants