Skip to content

fix(cache): recognize space, tab, and = as directive terminators in hasDirective#4211

Open
Yanhu007 wants to merge 2 commits intogofiber:mainfrom
Yanhu007:fix/cache-has-directive-terminators
Open

fix(cache): recognize space, tab, and = as directive terminators in hasDirective#4211
Yanhu007 wants to merge 2 commits intogofiber:mainfrom
Yanhu007:fix/cache-has-directive-terminators

Conversation

@Yanhu007
Copy link
Copy Markdown

Summary

Fixes #4143

The hasDirective function in the cache middleware only recognized , and end-of-string as valid terminators after a matched directive token. Per RFC 9111 §5.2, directives can also be followed by:

  • Space ( ) — e.g. no-cache or no-cache , max-age=0
  • Tab (\t) — whitespace in headers
  • = — directives with arguments, e.g. no-cache="Set-Cookie", max-age=3600

Missing these terminators could cause the cache middleware to serve cached responses that should not be cached (e.g. private or no-cache directives being ignored).

Changes

  • Accept , \t, and = as valid terminators after a directive match
  • Accept \t as a valid separator before a directive (alongside space and comma)
  • Added comprehensive unit tests for hasDirective covering all edge cases

Tests

All 16 test cases pass:

--- PASS: Test_hasDirective (0.00s)
    --- PASS: Test_hasDirective/trailing_space
    --- PASS: Test_hasDirective/trailing_tab
    --- PASS: Test_hasDirective/directive_with_equals
    ... (all 16 pass)

…asDirective

The hasDirective function only checked for ',' and end-of-string
after a matched directive token. This caused it to miss directives
followed by space, tab, or '=' (for directives with arguments):

  - 'no-cache ' (trailing space) → not detected
  - 'no-cache="Set-Cookie"' (directive with value) → not detected
  - 'private\t' (trailing tab) → not detected

This could cause the cache middleware to serve cached responses when
it shouldn't (e.g. a private response leaking into shared cache).

Also accept tab as a valid separator before a directive (in addition
to space and comma).

Fixes gofiber#4143
@Yanhu007 Yanhu007 requested a review from a team as a code owner April 12, 2026 03:07
@Yanhu007 Yanhu007 requested review from ReneWerner87, Copilot, efectn, gaby and sixcolors and removed request for Copilot April 12, 2026 03:07
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 940f817c-c7fa-4bc5-aafc-68252d11e0e2

📥 Commits

Reviewing files that changed from the base of the PR and between 1eefc14 and 05391d5.

📒 Files selected for processing (1)
  • middleware/cache/cache.go

Walkthrough

Updated cache middleware token-matching: hasDirective now recognizes directives followed by end-of-string, ,, space, tab, or = per RFC 9111 §5.2; added tests validating multiple boundary and casing scenarios.

Changes

Cohort / File(s) Summary
Cache directive matching logic
middleware/cache/cache.go
Adjusted hasDirective to treat directive termini as end-of-string, ,, space, tab, or = and broadened preceding-separator checks to include tab; updated doc comment to reference RFC 9111 §5.2.
Directive detection tests
middleware/cache/cache_test.go
Added Test_hasDirective table-driven unit test covering exact matches, comma-separated lists, start/end boundaries, non-matches/partials, trailing spaces/tabs, directives with = values, and case-insensitive matching.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

📜 RFC Compliance

Suggested reviewers

  • sixcolors
  • efectn
  • ReneWerner87

Poem

🐰 I sniffed the headers, sharp and spry,

Tabs and spaces, none slip by.
With = or comma, end or space,
RFC-guided hops—now every case.
Cache-control sings, no bugs to chase. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title directly reflects the main change: recognizing space, tab, and = as directive terminators in hasDirective function.
Description check ✅ Passed PR description clearly explains the bug, RFC reference, changes made, and includes test results, though formal checklist items are not addressed.
Linked Issues check ✅ Passed Code changes fully implement RFC 9111 §5.2 requirements: hasDirective now recognizes space, tab, and = as valid terminators/separators, and comprehensive unit tests validate all scenarios from issue #4143.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing hasDirective function behavior and adding corresponding tests; no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@ReneWerner87 ReneWerner87 added this to the v3 milestone Apr 12, 2026
@ReneWerner87 ReneWerner87 added this to v3 Apr 12, 2026
Copy link
Copy Markdown
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 updates the hasDirective function in the cache middleware to align with RFC 9111 §5.2. The logic now correctly handles tabs as separators and recognizes directives followed by an equals sign, supporting directives with values. A new test suite, Test_hasDirective, has been added to cover various edge cases including whitespace and case sensitivity. I have no feedback to provide.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 12, 2026

Codecov Report

❌ Patch coverage is 80.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 91.24%. Comparing base (c9f3475) to head (05391d5).

Files with missing lines Patch % Lines
middleware/cache/cache.go 80.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4211      +/-   ##
==========================================
+ Coverage   91.15%   91.24%   +0.08%     
==========================================
  Files         123      123              
  Lines       11860    11863       +3     
==========================================
+ Hits        10811    10824      +13     
+ Misses        660      652       -8     
+ Partials      389      387       -2     
Flag Coverage Δ
unittests 91.24% <80.00%> (+0.08%) ⬆️

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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the cache middleware’s directive detection to comply more closely with RFC 9111 Cache-Control directive syntax, preventing cache directives from being missed when followed by whitespace or =.

Changes:

  • Extend hasDirective terminator handling to include space, tab, and = (in addition to comma/end-of-string).
  • Allow tab as a valid separator before a directive in hasDirective.
  • Add unit tests covering whitespace and = edge cases for directive matching.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
middleware/cache/cache.go Expands hasDirective matching rules for RFC-compliant terminators/separators.
middleware/cache/cache_test.go Adds a focused test suite validating hasDirective behavior across edge cases.

Comment on lines 918 to 923
if i > 0 {
prev := cc[i-1]
if prev != ' ' && prev != ',' {
if prev != ' ' && prev != ',' && prev != '\t' {
continue
}
}
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

hasDirective now treats '\t' as a valid separator/terminator, but parseCacheControlDirectives (used by parseRequestCacheControl/parseResponseCacheControl) still only skips/trims spaces. This means Cache-Control directives preceded/followed by tabs (valid OWS) can still be missed in the main parsing path, potentially reintroducing incorrect caching decisions. Consider extending parseCacheControlDirectives to treat '\t' like ' ' when skipping leading separators and trimming key/value.

Copilot uses AI. Check for mistakes.
Comment on lines +5098 to +5104
tests := []struct {
name string
cc string
directive string
want bool
}{
// Basic matches
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

PR description mentions 16 hasDirective test cases, but this table currently defines 15. Either add the missing edge case (if intended) or update the PR description/test output snippet to match the actual count.

Copilot uses AI. Check for mistakes.
@gaby
Copy link
Copy Markdown
Member

gaby commented Apr 12, 2026

@Yanhu007 check the comments above and the failing spell-check workflow.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

🐛 [Bug]: Cache middleware hasDirective misses directives followed by space, tab, or '='

4 participants