|
| 1 | +--- |
| 2 | +title: Response Cache |
| 3 | +keywords: [higress,response cache] |
| 4 | +description: Response Cache Plugin Configuration Reference |
| 5 | +--- |
| 6 | +## Function Description |
| 7 | +Response caching plugin supports extracting keys from request headers/request bodies and caching values extracted from response bodies. On subsequent requests, if the request headers/request bodies contain the same key, it directly returns the cached value without forwarding the request to the backend service. |
| 8 | + |
| 9 | +**Hint** |
| 10 | + |
| 11 | +When carrying the request header `x-higress-skip-response-cache: on`, the current request will not use content from the cache but will be directly forwarded to the backend service. Additionally, the response content from this request will not be cached. |
| 12 | + |
| 13 | +## Runtime Properties |
| 14 | +Plugin Execution Phase: `Authentication Phase` |
| 15 | +Plugin Execution Priority: `10` |
| 16 | + |
| 17 | +## Configuration Description |
| 18 | + |
| 19 | +### Cache Service (cache) |
| 20 | +| Property | Type | Requirement | Default | Description | |
| 21 | +| --- | --- | --- | --- | --- | |
| 22 | +| cache.type | string | required | "" | Cache service type, e.g., redis | |
| 23 | +| cache.serviceName | string | required | "" | Cache service name | |
| 24 | +| cache.serviceHost | string | required | "" | Cache service domain | |
| 25 | +| cache.servicePort | int64 | optional | 6379 | Cache service port | |
| 26 | +| cache.username | string | optional | "" | Cache service username | |
| 27 | +| cache.password | string | optional | "" | Cache service password | |
| 28 | +| cache.timeout | uint32 | optional | 10000 | Timeout for cache service in milliseconds. Default is 10000, i.e., 10 seconds | |
| 29 | +| cache.cacheTTL | int | optional | 0 | Cache expiration time in seconds. Default is 0, meaning never expires | |
| 30 | +| cacheKeyPrefix | string | optional | "higress-response-cache:" | Prefix for cache keys, default is "higress-response-cache:" | | |
| 31 | + |
| 32 | +### Other Configurations |
| 33 | +| Name | Type | Requirement | Default | Description | |
| 34 | +| --- | --- | --- | --- | --- | |
| 35 | +| cacheResponseCode | array of number | optional | 200 | Indicates the list of response status codes that support caching; the default is 200.| |
| 36 | +| cacheKeyFromHeader | string | optional | "" | Extracts a fixed field's value from headers as the cache key; when configured, extracts key from request headers without reading the request body; **only one of cacheKeyFromHeader and cacheKeyFromBody can be configured when both are non-empty**| |
| 37 | +| cacheKeyFromBody | string | optional | "" | If empty, extracts all body as the cache key; otherwise, extracts a string from the request body in JSON format based on [GJSON PATH](https://github.com/tidwall/gjson/blob/master/SYNTAX.md); only takes effect when cacheKeyFromHeader is empty or not configured | |
| 38 | +| cacheValueFromBodyType | string | optional | "application/json" | Indicates the type of cached body; the content-type returned on cache hit will be this value; default is "application/json" | |
| 39 | +| cacheValueFromBody | string | optional | "" | If empty, caches all body; when cacheValueFromBodyType is "application/json", supports extracting a string from the response body based on [GJSON PATH](https://github.com/tidwall/gjson/blob/master/SYNTAX.md) | |
| 40 | + |
| 41 | + |
| 42 | +The logic for concatenating the cache key is one of the following: |
| 43 | + |
| 44 | +1. `cacheKeyPrefix` + content extracted from the field corresponding to `cacheKeyFromHeader` in the request header |
| 45 | +2. `cacheKeyPrefix` + content extracted from the field corresponding to `cacheKeyFromBody` in the request body |
| 46 | + |
| 47 | +**Note**: `cacheKeyFromHeader` and `cacheKeyFromBody` cannot be configured at the same time (only one of them can be configured when both are non-empty). If both are configured, the plugin will return an error during the configuration parsing phase. |
| 48 | + |
| 49 | +In the case of hitting the cache plugin, there are three statuses in the returned response headers: |
| 50 | + |
| 51 | +- `x-cache-status: hit` , indicating a cache hit and cached content is returned directly |
| 52 | +- `x-cache-status: miss` , indicating a cache miss and backend response results are returned |
| 53 | +- `x-cache-status: skip` , indicating skipping the cache check |
| 54 | + |
| 55 | +## Configuration Example |
| 56 | +### Basic Configuration |
| 57 | +```yaml |
| 58 | +cache: |
| 59 | + type: redis |
| 60 | + serviceName: my-redis.dns |
| 61 | + servicePort: 6379 |
| 62 | + timeout: 2000 |
| 63 | + |
| 64 | +cacheKeyFromHeader: "x-http-cache-key" |
| 65 | + |
| 66 | +cacheValueFromBodyType: "application/json" |
| 67 | +cacheValueFromBody: "messages.@reverse.0.content" |
| 68 | +``` |
| 69 | +
|
| 70 | +Assumed Request |
| 71 | +
|
| 72 | +```bash |
| 73 | +# Request |
| 74 | +curl -H "x-http-cache-key: abcd" <url> |
| 75 | + |
| 76 | +# Response |
| 77 | +{"messages":[{"content":"1"}, {"content":"2"}, {"content":"3"}]} |
| 78 | +``` |
| 79 | + |
| 80 | +In this case, the cache key would be `higress-response-cache:abcd`, and the cached value would be `3`. |
| 81 | + |
| 82 | +For subsequent requests that hit the cache, the response Content-Type returned is `application/json`. |
| 83 | + |
| 84 | +### Response Body as Cache Value |
| 85 | +To cache all response bodies, configure as follows: |
| 86 | + |
| 87 | +```yaml |
| 88 | +cacheValueFromBodyType: "text/html" |
| 89 | +cacheValueFromBody: "" |
| 90 | +``` |
| 91 | +For subsequent requests that hit the cache, the response Content-Type returned is `text/html`. |
| 92 | + |
| 93 | + |
| 94 | +### Request Body as Cache Key |
| 95 | +To use the request body as the key, configure as follows: |
| 96 | + |
| 97 | +```yaml |
| 98 | +
|
| 99 | +cacheKeyFromBody: "" |
| 100 | +``` |
| 101 | + |
| 102 | +The configuration supports GJSON PATH syntax. |
| 103 | + |
| 104 | + |
| 105 | +## Advanced Usage |
| 106 | +When the body is `application/json`, GJSON PATH syntax is supported: |
| 107 | + |
| 108 | +For example, the expression `messages.@reverse.0.content` means taking the content of the first item after reversing the messages array. |
| 109 | + |
| 110 | +GJSON PATH also supports conditional syntax. For instance, to take the content of the last message where role is "user", you can write: `messages.@reverse.#(role=="user").content`. |
| 111 | + |
| 112 | +To concatenate all contents where role is "user" into an array, you can write: `messages.@reverse.#(role=="user")#.content`. |
| 113 | + |
| 114 | +Pipeline syntax is also supported. For example, to take the second content where role is "user", you can write: `messages.@reverse.#(role=="user")#.content|1`. |
| 115 | + |
| 116 | +Refer to the [official documentation](https://github.com/tidwall/gjson/blob/master/SYNTAX.md) for more usage examples, and test the syntax using the [GJSON Playground](https://gjson.dev/). |
| 117 | + |
| 118 | +## Common Issues |
| 119 | +If the error `error status returned by host: bad argument` occurs, check: |
| 120 | +- Whether `serviceName` correctly includes the service type suffix (.dns, etc.) |
| 121 | +- Whether `servicePort` is configured correctly, especially that `static` type services now use a fixed port of 80 |
0 commit comments