Skip to content

Standardize Cache-Control Header Parsing Across SDK and Proxy - #34751

Open
ParvGatecha wants to merge 1 commit into
BerriAI:litellm_internal_stagingfrom
ParvGatecha:litellm_cache_control_header_parsing
Open

Standardize Cache-Control Header Parsing Across SDK and Proxy#34751
ParvGatecha wants to merge 1 commit into
BerriAI:litellm_internal_stagingfrom
ParvGatecha:litellm_cache_control_header_parsing

Conversation

@ParvGatecha

Copy link
Copy Markdown

Standardize Cache-Control Header Parsing Across SDK and Proxy

TLDR

Problem this solves:

  • Cache-Control headers were parsed in multiple locations with different logic.
  • SDK and Proxy could interpret the same header inconsistently.
  • Parsing behavior was harder to maintain and extend.

How it solves it:

  • Introduces a shared RFC-compliant Cache-Control parser.
  • Reuses the shared parser across SDK caching and Proxy.
  • Adds comprehensive unit tests covering common directives and edge cases.

Relevant issues

N/A


Linear ticket

N/A


Pre-Submission checklist

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review

Screenshots / Proof of Fix

Manual verification

The following scenarios were verified after the change:

  • Cache-Control: no-cache correctly bypasses cache usage.
  • Cache-Control: no-store is respected during cache storage decisions.
  • Cache-Control: max-age=<value> is parsed consistently across SDK and Proxy.
  • Mixed-case directives (for example No-Cache) are parsed correctly.
  • Headers with extra whitespace and comma-separated directives are handled correctly.
  • Quoted directive values are parsed correctly.
  • Existing caching behaviour remains backward compatible while using the shared parser.

Type

🧹 Refactoring


Changes

  • Added a shared parse_cache_control_header() utility under litellm_core_utils.
  • Standardized Cache-Control parsing across SDK caching components and the Proxy.
  • Updated cache decision logic to consistently respect Cache-Control headers supplied through request headers.
  • Replaced duplicated parsing logic with the shared implementation.
  • Added comprehensive unit tests covering RFC-compliant parsing behaviour and caching integration.
  • Preserved existing public APIs while improving consistency and maintainability.

Final Attestation

  • The tests check the right things, including edge cases, and help prevent regressions in Cache-Control parsing across the SDK and Proxy.

@CLAassistant

CLAassistant commented Jul 27, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@greptile-apps

greptile-apps Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Standardizes Cache-Control handling through a shared parser

  • Applies parsed request directives to SDK cache reads and writes
  • Reuses the parser in proxy request preparation
  • Adds parser and caching-handler unit coverage

Confidence Score: 3/5

The PR should not merge until valued no-cache directives bypass cache reads and lifetime directive precedence is made order-independent

Current parsing allows cache reuse despite a valid valued no-cache directive and can assign the wrong expiration when s-maxage and max-age appear together

Files Needing Attention: litellm/litellm_core_utils/cache_control_utils.py, litellm/caching/caching.py, litellm/caching/caching_handler.py, litellm/proxy/litellm_pre_call_utils.py

Important Files Changed

Filename Overview
litellm/litellm_core_utils/cache_control_utils.py Adds the shared parser, but mishandles valued no-cache and collapses distinct lifetime directives using order-dependent semantics
litellm/caching/caching.py Adds header-driven cache bypass, but only recognizes boolean no-cache
litellm/caching/caching_handler.py Enriches cache options before reads and writes, while inheriting the parser's directive-value defects
litellm/proxy/litellm_pre_call_utils.py Reuses parsed directives for proxy TTL and cache settings, exposing incorrect normalized lifetimes downstream
tests/test_litellm/litellm_core_utils/test_cache_control_utils.py Covers common parser forms but omits valued no-cache and conflicting lifetime directives
tests/test_litellm/caching/test_caching_handler.py Verifies basic header enrichment and explicit-cache precedence but not the failing edge cases

Reviews (1): Last reviewed commit: "feat(caching): standardize HTTP Cache-Co..." | Re-trigger Greptile

except ValueError:
parsed[raw_key] = raw_val
else:
parsed[raw_key] = raw_val

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Valued no-cache bypass is ignored

When a default-on cache receives a valued directive such as Cache-Control: no-cache="Authorization", the parser stores the value as a string while both cache-read guards recognize only the boolean True, causing the lookup to proceed and a stale cached response to be returned instead of invoking the provider.

Knowledge Base Used: Response Caching

Comment on lines +15 to +20
if raw_key in ("max-age", "s-maxage", "s-max-age", "ttl"):
try:
int_val = int(raw_val)
parsed["s-maxage"] = int_val
parsed["s-max-age"] = int_val
parsed["ttl"] = int_val

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Cache lifetime precedence is order-dependent

When a header contains different s-maxage and max-age values with max-age last, the parser overwrites every normalized lifetime key with max-age, causing the shared cache to use the wrong expiration and either evict entries prematurely or retain stale responses.

Knowledge Base Used: Response Caching

@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 70.31250% with 19 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
litellm/caching/caching.py 36.36% 7 Missing ⚠️
litellm/proxy/litellm_pre_call_utils.py 22.22% 7 Missing ⚠️
litellm/litellm_core_utils/cache_control_utils.py 87.50% 3 Missing ⚠️
litellm/caching/caching_handler.py 90.00% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing ParvGatecha:litellm_cache_control_header_parsing (4af4000) with litellm_internal_staging (2412326)

Open in CodSpeed

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