- policyRef: name: http-caching-flex config: httpCachingKey: <string> // REQUIRED, default: "#[attributes.requestPath]" maxCacheEntries: <int> // REQUIRED, default: 10000 ttl: <int> // REQUIRED, default: 600 useHttpCacheHeaders: <bool> // REQUIRED, default: true invalidationHeader: <string> // OPTIONAL, default: "" requestExpression: <string> // OPTIONAL, default: "#[attributes.method == 'GET' or attributes.method == 'HEAD']" responseExpression: <string> // OPTIONAL, default: "#[[200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501] contains attributes.statusCode]" distributed: <bool> // REQUIRED, default: false persistCache: <bool> // REQUIRED, default: false
HTTP Caching Policy
Policy Name |
HTTP caching |
Summary |
Caches HTTP responses from an API implementation |
Category |
Quality of Service |
First Flex Gateway version available |
v1.0.0 |
Returned Status Codes |
No return codes exist for this policy |
Summary
The HTTP Caching policy enables you to cache HTTP responses for reuse. Caching these responses speeds up the response time for user requests and reduces the load on the backend. For example, if your backend exposes an endpoint for which the responses to requests are not likely to change, you can reuse the HTTP responses and bypass the backend request processing by using the HTTP Caching policy.
Configuring Policy Parameters
Flex Gateway Local Mode
In Local Mode, you apply the HTTP Caching policy to your API via declarative configuration files. Refer to the following policy definition and table of parameters:
Parameter | Required or Optional | Default Value | Description |
---|---|---|---|
|
Required |
|
A DataWeave expression |
|
Required |
10000 |
Specifies the maximum number of entries that can be stored in the cache at any given time |
|
Required |
600 |
Specifies the amount of time (in seconds) after which a single entry expires from the cache |
|
Required |
true |
Enables the use of Cache-Control header directives |
|
Optional |
Empty string |
A string specifying the header used to invalidate a single entry or the entire cache |
|
Optional |
|
The DataWeave expression that is used to decide which requests are to be cached (caches the response only if the condition is true) |
|
Optional |
|
The DataWeave expression that is used to decide which responses are to be cached (caches the response only if the condition is true) |
|
Required |
false |
Configures the cache to be distributed among different nodes in a cluster |
|
Required |
false |
Configures the cache to persist between different restarts of the replica |
Leaving a required value blank configures the parameter as the default value. No value is configured for optional values left blank. |
Resource Configuration Example
- policyRef:
name: http-caching-flex
config:
httpCachingKey: "#[attributes.requestPath]"
maxCacheEntries: 10000
ttl: 500
useHttpCacheHeaders: false
requestExpression: "#[attributes.method == 'GET' or attributes.method == 'HEAD']"
responseExpression: "#[[200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501] contains attributes.statusCode]"
Distributed Caching Resource Configuration Example
Distributed Caching requires Shared Storage to be enabled. For more information about Shared Storage, refer to Configuring Shared Storage for Flex Gateway in Connected Mode.
--- apiVersion: gateway.mulesoft.com/v1alpha1 kind: Configuration metadata: name: shared-storage-redis spec: sharedStorage: redis: address: redis:6379 user: user password: pass DB: 1 --- apiVersion: gateway.mulesoft.com/v1alpha1 kind: PolicyBinding metadata: name: ingress-http-caching spec: targetRef: kind: ApiInstance name: ingress-http policyRef: kind: Extension name: http-caching-flex config: httpCachingKey: "#[attributes.method ++ attributes.requestPath]" useHttpCacheHeaders: true maxCacheEntries: 100 ttl: 600 distributed: true persistCache: true invalidationHeader: AGW-CACHE-CONTROL
Flex Gateway Connected Mode
When you apply the HTTP Caching policy to your API from the UI, you can configure the following parameters:
Parameter | Description | Required? |
---|---|---|
HTTP Caching Key |
A DataWeave expression.
Default value: |
Yes |
Maximum Cache Entries |
Specifies the maximum number of entries that can be stored in the cache at any given time.
Default value: |
Yes |
Entry Time To Live |
Specifies the amount of time (in seconds) after which a single entry expires from the cache.
Default value: |
Yes |
Distributed |
Configures the cache to be distributed among different nodes in a cluster.
Default value: |
Yes |
Persistent Cache |
Configures the cache to persist between different restarts of the Flex Gateway instance.
Default value: |
Yes |
Follow HTTP Caching directives |
Enables the use of Cache-Control header directives.
Default value: |
Yes |
Invalidation Header |
Name of the header used to invalidate a single entry or the entire cache. |
No |
Conditional Request Caching Expression |
The DataWeave expression that is used to decide which requests are to be cached (caches the response only if the condition is true).
Default value: |
No |
Conditional Response Caching Expression |
The DataWeave expression that is used to decide which responses are to be cached (caches the response only if the condition is true).
Default value: |
No |
How This Policy Works
When an HTTP request reaches an endpoint, what happens next depends on whether that request does not already exist in cache (a cache miss) or whether it does (a cache hit).
Cache Miss
In a cache miss scenario, the HTTP Caching policy checks whether a response to the submitted request is already cached. The request reaches the backend and the process is initiated only when it’s a cache miss. The diagram illustrates the flow of events that occur in this scenario:
-
The client (user) sends a request to the API.
-
The request proceeds through other policies in the policy chain before reaching the HTTP Caching policy.
-
The HTTP Caching policy checks if the request is already in the object store and, if not, the cache miss process is initiated.
-
The request continues throughout the chain of other remaining policies.
-
The request reaches the backend and completes all required processing.
-
The backend responds and the response travels back through the policy chain.
-
The response reaches the HTTP Caching policy.
-
Caching hits the object store again and attempts to save the key of the request for later reuse.
-
The response continues through the remaining policies in the policy chain.
-
The response is returned to the client.
Cache Hit
In a cache hit scenario, the HTTP Caching policy searches for the key in the object store and finds that the response to a request is already cached as a stored entry. The request does not proceed any further in the policy chain toward the backend, and the cached response is reused.
Subsequently, all the policies that must be executed in the policy chain after caching are not executed, in case of a cache hit:
-
The client (user) sends a request to the API.
-
The request crosses other policies before reaching the HTTP Caching policy.
-
The HTTP Caching policy verifies that the request is already in the cache.
-
The key is found in the object store and the stored response is returned.
-
The response continues through the rest of the policy chain until it reaches the last one.
-
The cached response is returned to the client.
Stored Entries
Stored entries are the cached HTTP responses. The cache can store any serializable data or input streams of up to 1 MB. If that value is surpassed, then the reading stops and the value is not stored in such a case.
HTTP Caching Key
The cache works as a dictionary, where each response stored in the cache is associated with a string called key. For example, the expression #[attributes.headers['key']] uses the header called key
as the entry key. You can use any DataWeave expression that returns a string, including predefined DataWeave variables.
Cache Size and Entry Expiration
The cache can hold a specified number of entries at any given time. You can configure this number using the Maximum Cache Entries
property. Each stored entry is held in the cache memory for a specific period of time, after which the entry expires and must be processed again. This expiration time is called time to live (TTL).
Another condition that can trigger the expiration of an entry is when the cache reaches the maximum number of items that it can store. When this scenario occurs, the entry is removed by using the FIFO (First-In First-Out) criteria. This means that the earliest entry to reach the cache is removed, even though it hasn’t reached the TTL value yet.
Distributed Cache
Each entry in the cache can be shared between different nodes in a cluster or between several workers in Runtime Manager using the Distributed
option (see table). If this option is not enabled, then each node is assigned its own cache memory.
Persistent Cache
A persistent cache enables the stored entries in the cache to persist if the Flex Replica is restarted.
When you upgrade a version of the instance that has the HTTP Caching policy configured to use the persistent store, the policy tries to maintain the entries stored by the previous version. However in a worst-case scenario, the entries in the cache are invalidated and the cache is re-populated when new requests arrive. This manipulation of the entries in the cache occurs automatically and is invisible to the user.
HTTP Caching Directives
To obtain more control over the cache, the HTTP Caching policy interprets some of the HTTP directives from the RFC-7234 protocol by taking the following headers into account:
-
Cache-Control
-
Expires
-
Date
-
Age
Cache-Control
The Cache-Control
header can exist either in the request or in the response. Possible values for the header, which can be combined separated by commas, include:
-
In requests:
-
no-cache
-
The response is not searched for, but is directly stored in the cache.
-
no-store
The response is not stored in the cache. However, if the response is already present in the cache, the policy returns the response.
-
In responses:
-
no-store
,no-cache
,private
-
For each value, the response is not stored in the cache.
-
max-age=<integer>
,s-maxage=<integer>
The <integer>
placeholder must be replaced with a valid integer that indicates the time (in seconds) for which the response can remain in the cache. If both parameters are defined, s-maxage
takes precedence over max-age
.
If a global time-to-live (TTL) value is also defined for the policy, these header values override the global TTL configured in the policy if the time specified in the headers is less than the global TTL.
Expires
If present, this header specifies the date by which the entry in the cache expires. If you specify the max-age
directive or s-maxage
directive, this header is ignored. You must define the header value as stated in RFC-1123.
Date
The date
header, as defined per RFC-1123, specifies the date and time when the response is created. If not defined, the date
header is added with the time when the request was received. This header is used in conjunction with the values defined in the max-age
and s-maxage
directives of the Cache-Control header.
Age
The age
header indicates the time (in seconds) elapsed since the origin of the cached response specified in the date header. This header is calculated by the policy and added to each response that is retrieved from the cache.
The expiration time is calculated using the cache-control
, date
, and expires
headers. However, if the resulting expiration time exceeds the one imposed by the TTL value of the entry, the cache entry expires anyway.
Invalidate
The invalidate
header, if configured in the HTTP Caching policy, invalidates the entries in the cache, thereby causing the request to be processed again. You specify the name of the header in the Invalidation Header configuration to turn on the option. The value of the header can take only one of the following options:
invalidate
This option invalidates the entry whose key matches the current request.
invalidate-all
This option invalidates all the entries from the cache.
For example, imagine that the following values are configured in the policy for the request:
-
HTTP Caching Key
: "#[attributes.requestPath]" -
Invalidation header
: "myInvalidationHeader"
The following command invalidates the entry with key “/my/policy" from the cache:
curl http://<MyAppURL>/my/policy -H “myInvalidationHeader:invalidate”
The following request invalidates all entries from the cache:
curl http://<MyAppURL>/my/policy -H “myInvalidationHeader:invalidate-all”
Conditional Caching
Conditional caching enables you to configure a set of conditions that must be met before entries are stored in the cache. If none of the conditional caching parameters are configured, the cache stores the responses for every incoming request. If configured, parameters are evaluated for each request to determine whether the response of the current request must be stored.
For conditional request expressions, only the responses for incoming requests with HTTP methods GET
or HEAD
are cached by default. For conditional response expressions, only status codes specified by RFC-7231 are cached by default.
For more information about the default values, see Configuring Policy Parameters.
FAQ
I’m using Postman or a similar tool and the policy isn’t caching anything?
When the Follow HTTP Caching directives parameter is true
, the policy follows the cache-control
header’s directive. By default, Postman and some other tools add the cache-control=no-cache
header to requests. Therefore, the policy ignores the cache unless Postman is configured otherwise.
What happens when the evaluation of the key results in any error?
If the evaluation of the expression for a particular request results in an error, the policy does not take effect and the request continues to the next receptor in the policy chain.
Can I store only part of the response with this policy?
No, but you can apply a policy before this one and transform the response to something else.
What happens if one parameter is configured to search for the response in the cache and the other parameter is configured for the opposite action?
This is the same as configuring the response to be stored in the cache when there is a no-store directive in the Cache-Control header.
In this situation, the response isn’t stored. You must configure both the Cache-Control header and the cache to be able to store and search for the response in the cache.
What happens if I do not define some of the optional parameters?
If you have not configured the invalidation
header, you cannot invalidate the cache in a request.
Additionally, if you have not configured the request expression or response expression, the cache is used for all requests and all the responses are stored in the cache (expression #[true]).
Can I modify the Invalidation header values?
No, you can modify only the header name.