Skip to content

cache: fix excessive caching and some other lack of caching #4335

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Aug 4, 2025

Conversation

fredericDelaporte
Copy link
Contributor

@fredericDelaporte fredericDelaporte commented Jul 14, 2025

307 responses must not be cached if they do not have an explicit caching directive.

Final responses with an explicit caching directive can be cached even if their status code is not heuristically cacheable status codes.

206 and 304 semantics are not handled by the cache and as such must not be cached.

This relates to...

fix #4334.

Changes

  • Cease caching 307 responses without caching directive.
  • Cache responses with explicit caching directive regardless of their status being heuristically cacheable.
  • Make sure 206 and 304 responses are not cached.

Features

N/A

Bug Fixes

Breaking Changes and Deprecations

N/A

Status

307 responses must not be cached if they do not have an explicit caching
directive.

Final responses with an explicit caching directive can be cached even if
their status code is not heuristically cacheable status codes.

fix part of nodejs#4334
@fredericDelaporte fredericDelaporte marked this pull request as ready for review July 14, 2025 13:16
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@mcollina
Copy link
Member

@fredericDelaporte could you check if there is any docs that needs updating?

@fredericDelaporte
Copy link
Contributor Author

I have put a "skipped" in the "Documented" item because I considered no documentation update was required. (Nothing documented about cache has changed, and the change is bug fixes and a slight improvement. I have also checked no mention of 307 being specifically cached were there.)

Maybe I should have instead ticked it for meaning I have done these checks?

Copy link
Member

@metcoder95 metcoder95 left a comment

Choose a reason for hiding this comment

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

lgtm, but CI seems red for cache

Comment on lines 259 to 273
if (cacheByDefault) {
// When cacheByDefault is truthy, the cache interceptor does no more mandate an explicit expiry prior to
// reaching here. We should then check the full condition allowing to consider caching responses.
// Responses with neither status codes that are heuristically cacheable, nor "explicit enough" caching
// directives, are not cacheable. "Explicit enough": see https://www.rfc-editor.org/rfc/rfc9111.html#section-3
if (!HEURISTICALLY_CACHEABLE_STATUS_CODES.includes(statusCode) && !resHeaders['expires'] &&
!cacheControlDirectives.public &&
cacheControlDirectives['max-age'] === undefined &&
// RFC 9111: a private response directive, if the cache is not shared
!(cacheControlDirectives.private && cacheType === 'private') &&
!(cacheControlDirectives['s-maxage'] !== undefined && cacheType === 'shared')
) {
return false
}
}
Copy link
Contributor Author

@fredericDelaporte fredericDelaporte Jul 16, 2025

Choose a reason for hiding this comment

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

When I considered the subject, I was not expecting it to turn that way because I was not aware of the cacheByDefault option.

Due to the code preceding the call to canCacheResponse, which actually does already some cacheability checks, we need that big test only when cacheByDefault is truthy.

See https://github.com/nodejs/undici/blob/4608ef157cc75d5ce3d2802e6949cb865d73146c/lib/handler/cache-handler.js#L115C1-L125C6

Maybe that code should be moved into canCacheResponse instead of staying out of it, allowing to have a better picture of how the cache interceptor checks cacheability.

@fredericDelaporte
Copy link
Contributor Author

The remaining CI failures seem to be a flaky websockets test. (There is a flaky cache test too which has blown on my setup once, name "revalidates the request when the response is stale".)

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@fredericDelaporte
Copy link
Contributor Author

Is there is something more I should do for this PR?

@metcoder95 metcoder95 merged commit c3f5591 into nodejs:main Aug 4, 2025
27 of 28 checks passed
@fredericDelaporte fredericDelaporte deleted the fixes/heuristic-cache branch August 6, 2025 12:00
@JoshMock JoshMock mentioned this pull request Aug 7, 2025
@github-actions github-actions bot mentioned this pull request Aug 17, 2025
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.

Excessive caching of some response cases, and lack of caching of some others
3 participants