Skip to content

Commit

Permalink
Add timeout to endpoint level cache config
Browse files Browse the repository at this point in the history
  • Loading branch information
furkansenharputlu committed Jul 27, 2023
1 parent 3c508e6 commit 73d1720
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 4 deletions.
1 change: 1 addition & 0 deletions apidef/api_definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ type CacheMeta struct {
Path string `bson:"path" json:"path"`
CacheKeyRegex string `bson:"cache_key_regex" json:"cache_key_regex"`
CacheOnlyResponseCodes []int `bson:"cache_response_codes" json:"cache_response_codes"`
Timeout int64 `bson:"timeout" json:"timeout"`
}

type RequestInputType string
Expand Down
2 changes: 2 additions & 0 deletions gateway/api_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ type EndPointCacheMeta struct {
Method string
CacheKeyRegex string
CacheOnlyResponseCodes []int
Timeout int64
}

type TransformSpec struct {
Expand Down Expand Up @@ -805,6 +806,7 @@ func (a APIDefinitionLoader) compileCachedPathSpec(oldpaths []string, newpaths [
newSpec.CacheConfig.Method = spec.Method
newSpec.CacheConfig.CacheKeyRegex = spec.CacheKeyRegex
newSpec.CacheConfig.CacheOnlyResponseCodes = spec.CacheOnlyResponseCodes
newSpec.CacheConfig.Timeout = spec.Timeout
// Extend with method actions
urlSpec = append(urlSpec, newSpec)
}
Expand Down
46 changes: 46 additions & 0 deletions gateway/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,52 @@ func TestOldCachePlugin(t *testing.T) {
})
}

func TestAdvanceCacheTimeoutPerEndpoint(t *testing.T) {
ts := StartTest(nil)
defer ts.Close()
cache := storage.RedisCluster{KeyPrefix: "cache-", RedisController: ts.Gw.RedisController}
defer cache.DeleteScanMatch("*")

extendedPaths := apidef.ExtendedPathsSet{
AdvanceCacheConfig: []apidef.CacheMeta{
{
Method: http.MethodGet,
Path: "/my-cached-endpoint",
},
},
}

api := BuildAPI(func(spec *APISpec) {
spec.Proxy.ListenPath = "/"
spec.CacheOptions = apidef.CacheOptions{
CacheTimeout: 0,
EnableCache: true,
}

UpdateAPIVersion(spec, "v1", func(v *apidef.VersionInfo) {
v.ExtendedPaths = extendedPaths
})
})[0]

ts.Gw.LoadAPI(api)

headerCache := map[string]string{"x-tyk-cached-response": "1"}

_, _ = ts.Run(t, []test.TestCase{
{Method: http.MethodGet, Path: "/my-cached-endpoint", HeadersNotMatch: headerCache, Delay: 10 * time.Millisecond},
{Method: http.MethodGet, Path: "/my-cached-endpoint", HeadersNotMatch: headerCache},
}...)

// endpoint level cache timeout should override
extendedPaths.AdvanceCacheConfig[0].Timeout = 120
ts.Gw.LoadAPI(api)

_, _ = ts.Run(t, []test.TestCase{
{Method: http.MethodGet, Path: "/my-cached-endpoint", HeadersNotMatch: headerCache, Delay: 10 * time.Millisecond},
{Method: http.MethodGet, Path: "/my-cached-endpoint", HeadersMatch: headerCache},
}...)
}

func TestWebsocketsSeveralOpenClose(t *testing.T) {
ts := StartTest(nil)
defer ts.Close()
Expand Down
16 changes: 13 additions & 3 deletions gateway/mw_redis_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ func (m *RedisCacheMiddleware) decodePayload(payload string) (string, string, er
type cacheOptions struct {
key string
cacheOnlyResponseCodes []int
timeout int64
}

// ProcessRequest will run any checks on the request on the way through the system, return an error to have the chain fail
Expand Down Expand Up @@ -193,14 +194,23 @@ func (m *RedisCacheMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Req
}

cacheOnlyResponseCodes := m.Spec.CacheOptions.CacheOnlyResponseCodes
// override api main CacheOnlyResponseCodes by endpoint specific if provided
if cacheMeta != nil && len(cacheMeta.CacheOnlyResponseCodes) > 0 {
cacheOnlyResponseCodes = cacheMeta.CacheOnlyResponseCodes
timeout := m.Spec.CacheOptions.CacheTimeout
if cacheMeta != nil {
// override api level CacheOnlyResponseCodes by endpoint level if provided
if len(cacheMeta.CacheOnlyResponseCodes) > 0 {
cacheOnlyResponseCodes = cacheMeta.CacheOnlyResponseCodes
}

// override api level Timout by endpoint level if provided
if cacheMeta.Timeout > 0 {
timeout = cacheMeta.Timeout
}
}

ctxSetCacheOptions(r, &cacheOptions{
key: key,
cacheOnlyResponseCodes: cacheOnlyResponseCodes,
timeout: timeout,
})

retBlob, err = m.store.GetKey(key)
Expand Down
2 changes: 1 addition & 1 deletion gateway/res_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (m *ResponseCacheMiddleware) HandleResponse(w http.ResponseWriter, res *htt
}

cacheThisRequest := true
cacheTTL := m.Spec.CacheOptions.CacheTimeout
cacheTTL := options.timeout

// make sure the status codes match if specified
if len(options.cacheOnlyResponseCodes) > 0 {
Expand Down

0 comments on commit 73d1720

Please sign in to comment.