Add LocalResponseCache filter to Spring Cloud Gateway Server Web MVC - #4249
Add LocalResponseCache filter to Spring Cloud Gateway Server Web MVC#4249nikita-kibitkin wants to merge 10 commits into
Conversation
Signed-off-by: Ingo Griebsch <ingo.griebsch@gmx.de>
…ions Signed-off-by: Ingo Griebsch <ingo.griebsch@gmx.de>
Signed-off-by: Ingo Griebsch <ingo.griebsch@gmx.de>
Signed-off-by: Ingo Griebsch <ingo.griebsch@gmx.de>
…ache' Signed-off-by: Ingo Griebsch <ingo.griebsch@gmx.de>
Signed-off-by: Ingo Griebsch <ingo.griebsch@gmx.de>
Signed-off-by: Ingo Griebsch <ingo.griebsch@gmx.de>
Signed-off-by: Ingo Griebsch <ingo.griebsch@gmx.de>
…ntation Signed-off-by: Ingo Griebsch <ingo.griebsch@gmx.de>
…teway Server Web MVC Implements the route-level LocalResponseCache filter for the Web MVC module, mirroring the cacheability semantics of the WebFlux filter: bodiless GET requests only, 200/206/301 responses, Cache-Control and Vary handling, no-cache revalidation, and max-age recalculation on cache hits. Backed by a per-route Caffeine cache with optional size-based eviction. The cache captures the response body at write time through a ServerResponse decorator, so the deferred proxy write path stays intact, composed filters keep working, and the cached body always belongs to the response that produced it. Writes that do not carry the full body are never cached: 304 Not Modified answers to conditional requests, async and view-rendering responses, writes with swallowed writer errors, and responses whose status was mutated after wrapping. Responses with a streaming media type are never cached. Both filter parameters are optional, matching the WebFlux configuration shortcut. Builds on the prototype started by Ingo Griebsch. Fixes spring-cloudgh-4182 Signed-off-by: Nikita Kibitkin <nikita.n.kibitkin@gmail.com>
|
I'm going to have to see how we handle this because you have included commits that are not yours. The earliest this would likely get merged is September or October |
|
The prototype commits are @ingogriebsch's, kept as-is so his authorship is preserved; each of them carries his own Signed-off-by. @ingogriebsch could you confirm here that you agree to your commits being included in this PR - and approve it if you think it is ready? If a different shape is easier to handle, tell me and I will rebase - for example squash the branch into a single commit with a Co-authored-by trailer. |
|
He didn't submit them to us. I'll get guidance from my team next week. |
|
@spencergibb I am the one who originally created Issue #4182. I had also created a fork and started working on the ticket. However, since I’m currently very busy and @nikita-kibitkin offered to take over the implementation, we agreed on how to proceed; he took over the codebase I had started and finalized it. The result is the current PR (which I personally haven’t had a chance to review yet). We weren’t aware that this might cause confusion and additional work; please accept our apologies. I’m still fine with Nikita taking over and continuing my commits. And I’m also fine with the PR being accepted. I hope this information helps your team decide how to proceed with this. Personally, I’d love it if the PR were accepted and the feature became available as soon as possible. :) |
|
Yes, thanks all. Based on team feedback, your response and the signed commits, everything is ok from our side. |
|
Just a reminder, new features don't go in patch releases and we won't branch for a new minor until probably September or October and ga in November. So it will be a while before this gets merged |
Summary
LocalResponseCachefilter to the Web MVC module, mirroring the cacheability semantics of the WebFlux filter: bodiless GET requests only, 200/206/301 responses, request/responseCache-Controlhandling,Varyhandling, no-cache revalidation, andmax-agerecalculation on cache hits@ConditionalOnClass) with optional size-based eviction; both filter parameters (timeToLive,size) are optional and default to 5 minutes / unboundedServerResponsedecorator, so the deferred proxy write path stays intact, composed filters keep working, and the cached body always belongs to the response that produced it; writes that do not carry the full body (304 answers to conditional requests, async and view-rendering responses, statuses mutated after wrapping, framing mismatches) are never cachedspring.cloud.gateway.server.webmvc.streaming-media-types)Builds on the prototype started by @ingogriebsch - his commits are kept in this branch. Ingo, a review from you would be very welcome.
Fixes gh-4182
Notes for reviewers
@ConfigurationPropertiesdefaults are intentionally out of scope for this PR; the docs reflect that.Cache-Controlvalues (private,no-store) are matched per header value rather than per directive,Vary: *is only detected as a standalone value,Set-Cookieheaders are cached and replayed, and there is no per-entry size cap. I can file a follow-up issue covering both stacks if that is preferred.ETagis answered with 304 from the cache (covered by tests).Testing
./mvnw -pl spring-cloud-gateway-server-webmvc -Dtest='ResponseCache*' test(37 unit + 16 integration tests)./mvnw -pl spring-cloud-gateway-server-webmvc test(full module green, including checkstyle)