Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
*** xref:spring-cloud-gateway-server-webmvc/filters/deduperesponseheader.adoc[]
*** xref:spring-cloud-gateway-server-webmvc/filters/fallback-headers.adoc[]
*** xref:spring-cloud-gateway-server-webmvc/filters/loadbalancer.adoc[]
//*** xref:spring-cloud-gateway-server-mvc/filters/local-cache-response-filter.adoc[]
*** xref:spring-cloud-gateway-server-webmvc/filters/local-cache-response-filter.adoc[]
*** xref:spring-cloud-gateway-server-webmvc/filters/maprequestheader.adoc[]
*** xref:spring-cloud-gateway-server-webmvc/filters/modifyrequestbody.adoc[]
*** xref:spring-cloud-gateway-server-webmvc/filters/modifyresponsebody.adoc[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,58 @@ This filter allows caching the response body and headers to follow these rules:
* It can only cache bodiless GET requests.
* It caches the response only for one of the following status codes: HTTP 200 (OK), HTTP 206 (Partial Content), or HTTP 301 (Moved Permanently).
* Response data is not cached if `Cache-Control` header does not allow it (`no-store` present in the request or `no-store` or `private` present in the response).
* If the response is already cached and a new request is performed with no-cache value in `Cache-Control` header, it returns a bodiless response with 304 (Not Modified).
* Response data is not cached if the response `Vary` header is `*`.
* Response data is not cached if the response has a streaming media type (see `spring.cloud.gateway.server.webmvc.streaming-media-types`).
* If a new request is performed with `no-cache` value in `Cache-Control` header, the request is forwarded to the upstream and the existing cache entry is kept.

This filter configures the local response cache per route and is available only if the `spring.cloud.gateway.filter.local-response-cache.enabled` property is enabled. And a xref:spring-cloud-gateway-server-webflux/global-filters.adoc#local-cache-response-global-filter[local response cache configured globally] is also available as feature.
This filter configures the local response cache per route.

It accepts the first parameter to override the time to expire a cache entry (expressed in `s` for seconds, `m` for minutes, and `h` for hours) and a second parameter to set the maximum size of the cache to evict entries for this route (`KB`, `MB`, or `GB`).
Both parameters are optional: if the time to live is not set, it defaults to 5 minutes; if the maximum size is not set, the cache is not size-bounded.

The following listing shows how to add local response cache filter:
The following listing shows how to add the local response cache filter:

[source,java]
----
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")
.filters(f -> f.prefixPath("/httpbin")
.localResponseCache(Duration.ofMinutes(30), "500MB")
).uri(uri))
.build();
}
----

or this

.application.yaml
.application.yml
[source,yaml]
----
spring:
cloud:
gateway:
routes:
- id: resource
uri: http://localhost:9000
predicates:
- Path=/resource
filters:
- LocalResponseCache=30m,500MB
server:
webmvc:
routes:
- id: resource
uri: http://localhost:9000
predicates:
- Path=/resource
filters:
- LocalResponseCache=30m,500MB
----

.GatewaySampleApplication.java
[source,java]
----
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
import static org.springframework.cloud.gateway.server.mvc.filter.ResponseCacheFilterFunctions.localResponseCache;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsCache() {
return route("resource")
.GET("/resource", http())
.before(uri("http://localhost:9000"))
.filter(localResponseCache(Duration.ofMinutes(30), DataSize.parse("500MB")))
.build();
}
}
----

NOTE: This filter also automatically calculates the `max-age` value in the HTTP `Cache-Control` header.
Only if `max-age` is present on the original response is the value rewritten with the number of seconds set in the `timeToLive` configuration parameter.
If `max-age` is not present on the original response, the value is set to the number of seconds set in the `timeToLive` configuration parameter.
In consecutive calls, this value is recalculated with the number of seconds left until the response expires.

NOTE: To enable this feature, add `com.github.ben-manes.caffeine:caffeine` and `spring-boot-starter-cache` as project dependencies.

WARNING: If your project creates custom `CacheManager` beans, it will either need to be marked with `@Primary` or injected using `@Qualifier`.


NOTE: To enable this feature, add `com.github.ben-manes.caffeine:caffeine` as a project dependency.
10 changes: 5 additions & 5 deletions spring-cloud-gateway-server-webmvc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@
<optional>true</optional>
</dependency>
<!-- Third party dependencies -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.bucket4j</groupId>
<artifactId>bucket4j_jdk17-core</artifactId>
Expand Down Expand Up @@ -163,11 +168,6 @@
<artifactId>bucket4j_jdk17-caffeine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-junit-jupiter</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import java.util.Objects;
import java.util.function.Function;

import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Weigher;
import io.github.bucket4j.BucketConfiguration;

import org.springframework.beans.factory.BeanFactory;
Expand Down Expand Up @@ -113,4 +115,15 @@ public TokenRelayFilterFunctions.FilterSupplier tokenRelayFilterFunctionsSupplie

}

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Weigher.class, Caffeine.class })
static class ResponseCacheFilterConfiguration {

@Bean
public ResponseCacheFilterFunctions.FilterSupplier responseCacheFilterFunctionsSupplier() {
return new ResponseCacheFilterFunctions.FilterSupplier();
}

}

}
Loading