diff --git a/README.md b/README.md index 5c5257d52..375c09256 100644 --- a/README.md +++ b/README.md @@ -925,7 +925,7 @@ experimental: plugins: souin: moduleName: github.com/darkweak/souin - version: v1.6.35 + version: v1.6.36 ``` After that you can declare either the whole configuration at once in the middleware block or by service. See the examples below. ```yaml diff --git a/configurationtypes/types.go b/configurationtypes/types.go index 45d9f5f8a..d829b5f1c 100644 --- a/configurationtypes/types.go +++ b/configurationtypes/types.go @@ -1,14 +1,106 @@ package configurationtypes import ( + "bytes" "encoding/json" + "fmt" "regexp" + "strconv" + "strings" "time" "go.uber.org/zap" yaml "gopkg.in/yaml.v3" ) +type CacheKey map[RegValue]Key +type CacheKeys []CacheKey + +func (c *CacheKeys) parseJSON(rootDecoder *json.Decoder) { + var token json.Token + var err error + + _, _ = rootDecoder.Token() + _, _ = rootDecoder.Token() + _, _ = rootDecoder.Token() + + for err == nil { + token, err = rootDecoder.Token() + key := Key{} + rg := fmt.Sprint(token) + + value := fmt.Sprint(token) + if value == "}" || token == nil { + continue + } + for value != "}" && token != nil { + token, _ = rootDecoder.Token() + value = fmt.Sprint(token) + switch value { + case "disable_body": + val, _ := rootDecoder.Token() + key.DisableBody, _ = strconv.ParseBool(fmt.Sprint(val)) + case "disable_host": + val, _ := rootDecoder.Token() + key.DisableHost, _ = strconv.ParseBool(fmt.Sprint(val)) + case "disable_method": + val, _ := rootDecoder.Token() + key.DisableMethod, _ = strconv.ParseBool(fmt.Sprint(val)) + case "disable_query": + val, _ := rootDecoder.Token() + key.DisableQuery, _ = strconv.ParseBool(fmt.Sprint(val)) + case "hide": + val, _ := rootDecoder.Token() + key.Hide, _ = strconv.ParseBool(fmt.Sprint(val)) + case "headers": + val, _ := rootDecoder.Token() + key.Headers = []string{} + for fmt.Sprint(val) != "]" { + val, _ = rootDecoder.Token() + header := fmt.Sprint(val) + if header != "]" { + key.Headers = append(key.Headers, header) + } + } + } + } + *c = append(*c, CacheKey{ + {Regexp: regexp.MustCompile(rg)}: key, + }) + } +} + +func (c *CacheKeys) UnmarshalYAML(value *yaml.Node) error { + for i := 0; i < len(value.Content)/2; i++ { + var cacheKey CacheKey + err := value.Decode(&cacheKey) + if err != nil { + return err + } + *c = append(*c, cacheKey) + } + + return nil +} + +func (c *CacheKeys) UnmarshalJSON(value []byte) error { + c.parseJSON(json.NewDecoder(bytes.NewBuffer(value))) + + return nil +} + +func (c *CacheKeys) MarshalJSON() ([]byte, error) { + var strKeys []string + for _, cacheKey := range *c { + for rg, key := range cacheKey { + keyBytes, _ := json.Marshal(key) + strKeys = append(strKeys, fmt.Sprintf(`"%s": %v`, rg.Regexp.String(), string(keyBytes))) + } + } + + return []byte(fmt.Sprintf(`{%s}`, strings.Join(strKeys, ","))), nil +} + // Duration is the super object to wrap the duration and be able to parse it from the configuration type Duration struct { time.Duration @@ -112,12 +204,12 @@ type CDN struct { } type Key struct { - DisableBody bool `json:"disable_body" yaml:"disable_body"` - DisableHost bool `json:"disable_host" yaml:"disable_host"` - DisableMethod bool `json:"disable_method" yaml:"disable_method"` - DisableQuery bool `json:"disable_query" yaml:"disable_query"` - Hide bool `json:"hide" yaml:"hide"` - Headers []string `json:"headers" yaml:"headers"` + DisableBody bool `json:"disable_body,omitempty" yaml:"disable_body,omitempty"` + DisableHost bool `json:"disable_host,omitempty" yaml:"disable_host,omitempty"` + DisableMethod bool `json:"disable_method,omitempty" yaml:"disable_method,omitempty"` + DisableQuery bool `json:"disable_query,omitempty" yaml:"disable_query,omitempty"` + Hide bool `json:"hide,omitempty" yaml:"hide,omitempty"` + Headers []string `json:"headers,omitempty" yaml:"headers,omitempty"` } // DefaultCache configuration @@ -287,5 +379,5 @@ type AbstractConfigurationInterface interface { SetLogger(*zap.Logger) GetYkeys() map[string]SurrogateKeys GetSurrogateKeys() map[string]SurrogateKeys - GetCacheKeys() map[RegValue]Key + GetCacheKeys() CacheKeys } diff --git a/context/key.go b/context/key.go index b00744c41..ca09baaaf 100644 --- a/context/key.go +++ b/context/key.go @@ -21,7 +21,7 @@ type keyContext struct { disable_query bool displayable bool headers []string - overrides map[*regexp.Regexp]keyContext + overrides []map[*regexp.Regexp]keyContext } func (g *keyContext) SetupContext(c configurationtypes.AbstractConfigurationInterface) { @@ -33,16 +33,18 @@ func (g *keyContext) SetupContext(c configurationtypes.AbstractConfigurationInte g.displayable = !k.Hide g.headers = k.Headers - g.overrides = make(map[*regexp.Regexp]keyContext) - - for r, v := range c.GetCacheKeys() { - g.overrides[r.Regexp] = keyContext{ - disable_body: v.DisableBody, - disable_host: v.DisableHost, - disable_method: v.DisableMethod, - disable_query: v.DisableQuery, - displayable: v.Hide, - headers: v.Headers, + g.overrides = make([]map[*regexp.Regexp]keyContext, 0) + + for _, cacheKey := range c.GetCacheKeys() { + for r, v := range cacheKey { + g.overrides = append(g.overrides, map[*regexp.Regexp]keyContext{r.Regexp: { + disable_body: v.DisableBody, + disable_host: v.DisableHost, + disable_method: v.DisableMethod, + disable_query: v.DisableQuery, + displayable: !v.Hide, + headers: v.Headers, + }}) } } } @@ -83,30 +85,39 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { headerValues += "-" + req.Header.Get(hn) } - for k, v := range g.overrides { - if k.MatchString(req.RequestURI) { - displayable = v.displayable - host = "" - method = "" - if !v.disable_query && len(req.URL.RawQuery) > 0 { - query = "?" + req.URL.RawQuery - } - if !v.disable_body { - body = req.Context().Value(HashBody).(string) - } - if !v.disable_method { - method = req.Method + "-" - } - if !v.disable_host { - host = req.Host + "-" - } - if len(v.headers) > 0 { - headerValues = "" - for _, hn := range v.headers { - headers = v.headers - headerValues += "-" + req.Header.Get(hn) + hasOverride := false + for _, current := range g.overrides { + for k, v := range current { + if k.MatchString(req.RequestURI) { + displayable = v.displayable + host = "" + method = "" + query = "" + if !v.disable_query && len(req.URL.RawQuery) > 0 { + query = "?" + req.URL.RawQuery + } + if !v.disable_body { + body = req.Context().Value(HashBody).(string) } + if !v.disable_method { + method = req.Method + "-" + } + if !v.disable_host { + host = req.Host + "-" + } + if len(v.headers) > 0 { + headerValues = "" + for _, hn := range v.headers { + headers = v.headers + headerValues += "-" + req.Header.Get(hn) + } + } + hasOverride = true + break } + } + + if hasOverride { break } } diff --git a/context/key_test.go b/context/key_test.go index e9bfec3e7..47832721b 100644 --- a/context/key_test.go +++ b/context/key_test.go @@ -25,13 +25,16 @@ func Test_KeyContext_SetupContext(t *testing.T) { t.Errorf("The method must be disabled.") } - m := make(map[configurationtypes.RegValue]configurationtypes.Key) rg := configurationtypes.RegValue{ Regexp: regexp.MustCompile(".*"), } - m[rg] = configurationtypes.Key{ - DisableHost: true, - DisableMethod: true, + m := configurationtypes.CacheKeys{ + { + rg: configurationtypes.Key{ + DisableHost: true, + DisableMethod: true, + }, + }, } ctx.SetupContext(&configuration.Configuration{ DefaultCache: &configurationtypes.DefaultCache{ @@ -49,10 +52,10 @@ func Test_KeyContext_SetupContext(t *testing.T) { if !ctx.disable_method { t.Errorf("The method must be enabled.") } - if !ctx.overrides[rg.Regexp].disable_host { + if !ctx.overrides[0][rg.Regexp].disable_host { t.Errorf("The host must be enabled.") } - if !ctx.overrides[rg.Regexp].disable_method { + if !ctx.overrides[0][rg.Regexp].disable_method { t.Errorf("The method must be enabled.") } } @@ -65,30 +68,32 @@ func Test_KeyContext_SetContext(t *testing.T) { t.Errorf("The Key context must be equal to GET-http-domain.com--with_the_hash, %s given.", req.Context().Value(Key).(string)) } - m := make(map[*regexp.Regexp]keyContext) - m[regexp.MustCompile("/matched")] = keyContext{ - disable_host: false, - disable_method: true, + m := map[*regexp.Regexp]keyContext{ + regexp.MustCompile("/matched"): { + disable_host: true, + disable_method: false, + }, } ctx2 := keyContext{ disable_host: true, disable_method: true, - overrides: m, + overrides: []map[*regexp.Regexp]keyContext{m}, } req2 := httptest.NewRequest(http.MethodGet, "http://domain.com/matched", nil) req2 = ctx2.SetContext(req2.WithContext(context.WithValue(req2.Context(), HashBody, ""))) - if req2.Context().Value(Key).(string) != "http-domain.com-/matched" { - t.Errorf("The Key context must be equal to http-domain.com-/matched, %s given.", req2.Context().Value(Key).(string)) + if req2.Context().Value(Key).(string) != "GET-http-/matched" { + t.Errorf("The Key context must be equal to GET-http-/matched, %s given.", req2.Context().Value(Key).(string)) } - m = make(map[*regexp.Regexp]keyContext) - m[regexp.MustCompile("/matched")] = keyContext{ - disable_host: true, - disable_method: false, + m = map[*regexp.Regexp]keyContext{ + regexp.MustCompile("/matched"): { + disable_host: true, + disable_method: false, + }, } ctx3 := keyContext{ disable_method: true, - overrides: m, + overrides: []map[*regexp.Regexp]keyContext{m}, } req3 := httptest.NewRequest(http.MethodGet, "http://domain.com/matched", nil) req3 = ctx3.SetContext(req3.WithContext(context.WithValue(req3.Context(), HashBody, ""))) diff --git a/pkg/middleware/configuration.go b/pkg/middleware/configuration.go index ed8f1825b..b408830b6 100644 --- a/pkg/middleware/configuration.go +++ b/pkg/middleware/configuration.go @@ -7,11 +7,11 @@ import ( // BaseConfiguration holder type BaseConfiguration struct { - DefaultCache *configurationtypes.DefaultCache `json:"default_cache" yaml:"default_cache"` - API configurationtypes.API `json:"api" yaml:"api"` - CacheKeys map[configurationtypes.RegValue]configurationtypes.Key `yaml:"cache_keys"` - URLs map[string]configurationtypes.URL `json:"urls" yaml:"urls"` - LogLevel string `json:"log_level" yaml:"log_level"` + DefaultCache *configurationtypes.DefaultCache `json:"default_cache" yaml:"default_cache"` + API configurationtypes.API `json:"api" yaml:"api"` + CacheKeys configurationtypes.CacheKeys `json:"cache_keys" yaml:"cache_keys"` + URLs map[string]configurationtypes.URL `json:"urls" yaml:"urls"` + LogLevel string `json:"log_level" yaml:"log_level"` Logger *zap.Logger Ykeys map[string]configurationtypes.SurrogateKeys `json:"ykeys" yaml:"ykeys"` SurrogateKeys map[string]configurationtypes.SurrogateKeys `json:"surrogate_keys" yaml:"surrogate_keys"` @@ -58,7 +58,7 @@ func (c *BaseConfiguration) GetSurrogateKeys() map[string]configurationtypes.Sur } // GetCacheKeys get the cache keys rules to override -func (c *BaseConfiguration) GetCacheKeys() map[configurationtypes.RegValue]configurationtypes.Key { +func (c *BaseConfiguration) GetCacheKeys() configurationtypes.CacheKeys { return c.CacheKeys } diff --git a/plugins/beego/go.mod b/plugins/beego/go.mod index af89fd8cd..a0e9867c6 100644 --- a/plugins/beego/go.mod +++ b/plugins/beego/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/beego/beego/v2 v2.0.7 - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 ) require ( @@ -86,4 +86,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/caddy/app.go b/plugins/caddy/app.go index 9fe513d3c..1a9c4237b 100644 --- a/plugins/caddy/app.go +++ b/plugins/caddy/app.go @@ -17,7 +17,7 @@ type SouinApp struct { // Surrogate storage to support th econfiguration reload without surrogate-key data loss. SurrogateStorage providers.SurrogateInterface // Cache-key tweaking. - CacheKeys map[string]configurationtypes.Key `json:"cache_keys,omitempty"` + CacheKeys configurationtypes.CacheKeys `json:"cache_keys,omitempty"` // API endpoints enablers. API configurationtypes.API `json:"api,omitempty"` // Logger level, fallback on caddy's one when not redefined. diff --git a/plugins/caddy/configuration.go b/plugins/caddy/configuration.go index 73b99bbd0..df4f612da 100644 --- a/plugins/caddy/configuration.go +++ b/plugins/caddy/configuration.go @@ -1,6 +1,7 @@ package httpcache import ( + "regexp" "strconv" "strings" "time" @@ -132,14 +133,13 @@ type Configuration struct { // API endpoints enablers. API configurationtypes.API // Cache keys configuration. - CfgCacheKeys map[string]configurationtypes.Key + CacheKeys configurationtypes.CacheKeys `json:"cache_keys"` // Override the ttl depending the cases. URLs map[string]configurationtypes.URL // Logger level, fallback on caddy's one when not redefined. LogLevel string // SurrogateKeys contains the surrogate keys to use with a predefined mapping SurrogateKeys map[string]configurationtypes.SurrogateKeys - cacheKeys map[configurationtypes.RegValue]configurationtypes.Key logger *zap.Logger } @@ -184,8 +184,8 @@ func (c *Configuration) GetSurrogateKeys() map[string]configurationtypes.Surroga } // GetCacheKeys get the cache keys rules to override -func (c *Configuration) GetCacheKeys() map[configurationtypes.RegValue]configurationtypes.Key { - return c.cacheKeys +func (c *Configuration) GetCacheKeys() configurationtypes.CacheKeys { + return c.CacheKeys } var _ configurationtypes.AbstractConfigurationInterface = (*Configuration)(nil) @@ -314,9 +314,9 @@ func parseConfiguration(cfg *Configuration, h *caddyfile.Dispenser, isBlocking b } cfg.DefaultCache.Badger = provider case "cache_keys": - cacheKeys := cfg.CfgCacheKeys - if cacheKeys == nil { - cacheKeys = make(map[string]configurationtypes.Key) + CacheKeys := cfg.CacheKeys + if CacheKeys == nil { + CacheKeys = make(configurationtypes.CacheKeys, 0) } for nesting := h.Nesting(); h.NextBlock(nesting); { rg := h.Val() @@ -340,9 +340,9 @@ func parseConfiguration(cfg *Configuration, h *caddyfile.Dispenser, isBlocking b } } - cacheKeys[rg] = ck + CacheKeys = append(CacheKeys, configurationtypes.CacheKey{configurationtypes.RegValue{Regexp: regexp.MustCompile(rg)}: ck}) } - cfg.CfgCacheKeys = cacheKeys + cfg.CacheKeys = CacheKeys case "cache_name": args := h.RemainingArgs() cfg.DefaultCache.CacheName = args[0] diff --git a/plugins/caddy/configuration.json b/plugins/caddy/configuration.json index 44f5df253..04345e36e 100644 --- a/plugins/caddy/configuration.json +++ b/plugins/caddy/configuration.json @@ -1,4254 +1,4031 @@ { - "apps": { - "cache": { - "allowed_http_verbs": [ - "GET", - "POST" - ], - "api": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": true, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": true, - "security": false - } - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": { - "dynamic": true, - "strategy": "hard" - }, - "default_cache_control": "public", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": [], - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "/test2.*" - }, - "stale": "0s", - "timeout": { - "backend": "10s", - "cache": "100ms" - }, - "ttl": "16m40s" - }, - "http": { - "servers": { - "srv0": { - "listen": [ - ":4443" - ], - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "apps": { + "cache": { + "allowed_http_verbs": [ + "GET", + "POST" + ], + "api": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": true, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": true, + "security": false } - ], - "match": [ - { - "path": [ - "/souin-api*" - ] - } - ] }, - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "5s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - } - ], - "match": [ - { - "path": [ - "/default" - ] - } - ] + "badger": { + "configuration": null, + "path": "", + "url": "" }, - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "5s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - } - ], - "match": [ - { - "path": [ - "/test1*" - ] - } - ] + "cache_name": "", + "cdn": { + "dynamic": true, + "strategy": "hard" }, - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "50s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - } - ], - "match": [ - { - "path": [ - "/test2*" - ] - } - ] + "default_cache_control": "public", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "Another", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/another-cache-status-name" - ] - } - ] + "headers": [], + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": { - "Dir": "/tmp/badger-configuration", - "MemTableSize": 4194304, - "ValueDir": "match2", - "ValueLogFileSize": 16777216, - "ValueThreshold": 524288 - }, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "15s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - { - "body": "Hello badger", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/badger-configuration" - ] - } - ] + "olric": { + "configuration": null, + "path": "", + "url": "" }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": { - "body": { - "disable_body": true, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "everything-with-content-type": { - "disable_body": false, - "disable_host": false, - "disable_method": true, - "headers": [ - "Content-Type" - ], - "hide": false - }, - "host": { - "disable_body": false, - "disable_host": true, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "method": { - "disable_body": false, - "disable_host": false, - "disable_method": true, - "headers": null, - "hide": false - } - }, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - { - "body": "Hello to the authenticated user.", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/custom-key/without-*" - ] - } - ] + "redis": { + "configuration": null, + "path": "", + "url": "" }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": true, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": { - "Addr": "127.0.0.1:6379", - "ConnMaxIdleTime": 5000000000, - "ConnMaxLifetime": 5000000000, - "DB": 0, - "DialTimeout": 5000000000, - "MaxIdleConns": 100, - "MaxRetries": 1, - "MaxRetryBackoff": 5000000000, - "MinIdleConns": 100, - "MinRetryBackoff": 5000000000, - "PoolFIFO": true, - "PoolSize": 99999, - "PoolTimeout": 10000000000, - "ReadTimeout": 5000000000, - "WriteTimeout": 5000000000 - }, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "5s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - { - "body": "Hello redis", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/redis-configuration" - ] - } - ] + "regex": { + "exclude": "/test2.*" }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": { - "/.+": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": [ - "Authorization" - ], - "hide": false - } - }, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - { - "handler": "headers", - "response": { - "set": { - "Souin-Cache-Control": [ - "public" - ] - } - } - }, - { - "body": "Hello to the authenticated user.", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/cache-authorization" - ] - } - ] + "stale": "0s", + "timeout": { + "backend": "10s", + "cache": "100ms" }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ + "ttl": "16m40s" + }, + "http": { + "servers": { + "srv0": { + "listen": [ + ":4443" + ], + "routes": [ { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": true, - "etcd": { - "configuration": { - "AutoSyncInterval": "1s", - "DialKeepAliveTime": "1s", - "DialKeepAliveTimeout": "1s", - "DialTimeout": "1s", - "Endpoints": [ - "etcd:2379", - "etcd:2379" - ], - "MaxCallRecvMsgSize": "10000000", - "MaxCallSendMsgSize": "10000000", - "PermitWithoutStream": "false", - "RejectOldCluster": "false" - }, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "5s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + } + ], + "match": [ + { + "path": [ + "/souin-api*" + ] + } + ] }, { - "body": "Hello etcd", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/etcd-configuration" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": { - "Dir": "/tmp/nuts-configuration", - "EntryIdxMode": "1", - "NodeNum": "42", - "RWMode": "0", - "SegmentSize": "1024", - "StartFileLoadingMode": "1", - "SyncEnable": "true" - }, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "15s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "5s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + } + ], + "match": [ + { + "path": [ + "/default" + ] + } + ] }, { - "body": "Hello nuts", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/nuts-configuration" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "5s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + } + ], + "match": [ + { + "path": [ + "/test1*" + ] + } + ] }, { - "handler": "reverse_proxy", - "upstreams": [ - { - "dial": "127.0.0.1:9000" - } - ] - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/no-reverse-proxy" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "1s", - "cache": "1ms" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "50s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + } + ], + "match": [ + { + "path": [ + "/test2*" + ] + } + ] }, { - "handler": "reverse_proxy", - "upstreams": [ - { - "dial": "127.0.0.1:8081" - } - ] - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/backend-timeout" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "Another", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/another-cache-status-name" + ] + } + ] }, { - "handler": "headers", - "response": { - "set": { - "Content-Type": [ - "text/html" - ] - } - } + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": { + "Dir": "/tmp/badger-configuration", + "MemTableSize": 4194304, + "ValueDir": "match2", + "ValueLogFileSize": 16777216, + "ValueThreshold": 524288 + }, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "15s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "body": "Hello badger", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/badger-configuration" + ] + } + ] }, { - "body": "\u003ch1\u003eALTERNATE ESI INCLUDE\u003c/h1\u003e", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/alt-esi-include" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": true, + "etcd": { + "configuration": { + "AutoSyncInterval": "1s", + "DialKeepAliveTime": "1s", + "DialKeepAliveTimeout": "1s", + "DialTimeout": "1s", + "Endpoints": [ + "etcd1:2379", + "etcd2:2379", + "etcd3:2379" + ], + "MaxCallRecvMsgSize": "10000000", + "MaxCallSendMsgSize": "10000000", + "Password": "doe", + "PermitWithoutStream": "false", + "RejectOldCluster": "false", + "Username": "john" + }, + "path": "", + "url": "" + }, + "headers": null, + "key": { + "disable_body": false, + "disable_host": false, + "disable_method": false, + "disable_query": false, + "headers": null, + "hide": false + }, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "5s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": { + "disable_body": false, + "disable_host": false, + "disable_method": false, + "disable_query": false, + "headers": null, + "hide": false + }, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "body": "Hello etcd", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/etcd" + ] + } + ] }, { - "handler": "headers", - "response": { - "set": { - "Cache-Control": [ - "s-maxage=10" - ] - } - } + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": true, + "etcd": { + "configuration": { + "AutoSyncInterval": "1s", + "DialKeepAliveTime": "1s", + "DialKeepAliveTimeout": "1s", + "DialTimeout": "1s", + "Endpoints": [ + "etcd:2379", + "etcd:2379" + ], + "MaxCallRecvMsgSize": "10000000", + "MaxCallSendMsgSize": "10000000", + "PermitWithoutStream": "false", + "RejectOldCluster": "false" + }, + "path": "", + "url": "" + }, + "headers": null, + "key": { + "disable_body": false, + "disable_host": false, + "disable_method": false, + "disable_query": false, + "headers": null, + "hide": false + }, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "5s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": { + "disable_body": false, + "disable_host": false, + "disable_method": false, + "disable_query": false, + "headers": null, + "hide": false + }, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "body": "Hello etcd", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/etcd-configuration" + ] + } + ] }, { - "body": "Hello, s-maxage!", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/cache-s-maxage" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "5s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "3s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": true, + "etcd": { + "configuration": { + "AutoSyncInterval": "1s", + "DialKeepAliveTime": "1s", + "DialKeepAliveTimeout": "1s", + "DialTimeout": "1s", + "Endpoints": [ + "etcd:2379", + "etcd:2379" + ], + "MaxCallRecvMsgSize": "10000000", + "MaxCallSendMsgSize": "10000000", + "PermitWithoutStream": "false", + "RejectOldCluster": "false" + }, + "path": "", + "url": "" + }, + "headers": null, + "key": { + "disable_body": false, + "disable_host": false, + "disable_method": false, + "disable_query": false, + "headers": null, + "hide": false + }, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "5s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": { + "disable_body": false, + "disable_host": false, + "disable_method": false, + "disable_query": false, + "headers": null, + "hide": false + }, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "body": "Hello etcd", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/etcd-configuration" + ] + } + ] }, { - "handler": "headers", - "response": { - "set": { - "Cache-Control": [ - "max-age=5" - ] - } - } + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": { + "body": { + "disable_body": true + }, + "everything-with-content-type": { + "disable_method": true, + "headers": [ + "Content-Type" + ] + }, + "host": { + "disable_host": true + }, + "method": { + "disable_method": true + } + } + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "body": "Hello to the authenticated user.", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/custom-key/without-*" + ] + } + ] }, { - "body": "Hello, max-age!", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/cache-maxstale" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": true, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": { + "Addr": "127.0.0.1:6379", + "ConnMaxIdleTime": 5000000000, + "ConnMaxLifetime": 5000000000, + "DB": 0, + "DialTimeout": 5000000000, + "MaxIdleConns": 100, + "MaxRetries": 1, + "MaxRetryBackoff": 5000000000, + "MinIdleConns": 100, + "MinRetryBackoff": 5000000000, + "PoolFIFO": true, + "PoolSize": 99999, + "PoolTimeout": 10000000000, + "ReadTimeout": 5000000000, + "WriteTimeout": 5000000000 + }, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "5s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "body": "Hello redis", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/redis-configuration" + ] + } + ] }, { - "handler": "headers", - "response": { - "set": { - "Surrogate-Key": [ - "KEY-{http.request.header.X-Surrogate-Key-Suffix}" - ] - } - } + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": { + "/.+": { + "headers": [ + "Authorization" + ] + } + } + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "headers", + "response": { + "set": { + "Souin-Cache-Control": [ + "public" + ] + } + } + }, + { + "body": "Hello to the authenticated user.", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/cache-authorization" + ] + } + ] }, { - "handler": "headers", - "response": { - "set": { - "Vary": [ - "X-Surrogate-Key-Suffix,Accept-Encoding" - ] - } - } + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": { + "Dir": "/tmp/nuts-configuration", + "EntryIdxMode": "1", + "NodeNum": "42", + "RWMode": "0", + "SegmentSize": "1024", + "StartFileLoadingMode": "1", + "SyncEnable": "true" + }, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "15s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "body": "Hello nuts", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/nuts-configuration" + ] + } + ] }, { - "body": "Hello {http.request.header.X-Surrogate-Key-Suffix}", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/surrogate-keys" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - { - "handler": "headers", - "response": { - "set": { - "Cache-Control": [ - "max-age=5" - ] - } - } + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "reverse_proxy", + "upstreams": [ + { + "dial": "127.0.0.1:9000" + } + ] + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/no-reverse-proxy" + ] + } + ] }, { - "body": "Hello, max-age!", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/cache-maxage" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "5s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "1s", + "cache": "1ms" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "reverse_proxy", + "upstreams": [ + { + "dial": "127.0.0.1:8081" + } + ] + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/backend-timeout" + ] + } + ] }, { - "handler": "reverse_proxy", - "upstreams": [ - { - "dial": "127.0.0.1:9000" - } - ] - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/not-modified" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "headers", + "response": { + "set": { + "Content-Type": [ + "text/html" + ] + } + } + }, + { + "body": "\u003ch1\u003eALTERNATE ESI INCLUDE\u003c/h1\u003e", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/alt-esi-include" + ] + } + ] }, { - "handler": "headers", - "response": { - "set": { - "Content-Type": [ - "text/html" - ] - } - } + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "headers", + "response": { + "set": { + "Cache-Control": [ + "s-maxage=10" + ] + } + } + }, + { + "body": "Hello, s-maxage!", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/cache-s-maxage" + ] + } + ] }, { - "body": "\u003ch1\u003eESI INCLUDE\u003c/h1\u003e", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/esi-include" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": true, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "127.0.0.1:6379" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "5s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "5s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "3s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "headers", + "response": { + "set": { + "Cache-Control": [ + "max-age=5" + ] + } + } + }, + { + "body": "Hello, max-age!", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/cache-maxstale" + ] + } + ] }, { - "body": "Hello redis url", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/redis-url" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "headers", + "response": { + "set": { + "Surrogate-Key": [ + "KEY-{http.request.header.X-Surrogate-Key-Suffix}" + ] + } + } + }, + { + "handler": "headers", + "response": { + "set": { + "Vary": [ + "X-Surrogate-Key-Suffix,Accept-Encoding" + ] + } + } + }, + { + "body": "Hello {http.request.header.X-Surrogate-Key-Suffix}", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/surrogate-keys" + ] + } + ] }, { - "handler": "reverse_proxy", - "upstreams": [ - { - "dial": "127.0.0.1:81" - } - ] - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/stream" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": true, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": { - "Addr": "127.0.0.1:6379", - "ConnMaxIdleTime": 5000000000, - "ConnMaxLifetime": 5000000000, - "DB": 1, - "DialTimeout": 5000000000, - "MaxIdleConns": 100, - "MaxRetries": 1, - "MaxRetryBackoff": 5000000000, - "MinIdleConns": 100, - "MinRetryBackoff": 5000000000, - "Network": "my-network", - "Password": "password", - "PoolFIFO": true, - "PoolSize": 99999, - "PoolTimeout": 10000000000, - "ReadTimeout": 5000000000, - "Username": "user", - "WriteTimeout": 5000000000 - }, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "5s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "headers", + "response": { + "set": { + "Cache-Control": [ + "max-age=5" + ] + } + } + }, + { + "body": "Hello, max-age!", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/cache-maxage" + ] + } + ] }, { - "body": "Hello redis", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/redis" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": true, - "etcd": { - "configuration": { - "AutoSyncInterval": "1s", - "DialKeepAliveTime": "1s", - "DialKeepAliveTimeout": "1s", - "DialTimeout": "1s", - "Endpoints": [ - "etcd1:2379", - "etcd2:2379", - "etcd3:2379" - ], - "MaxCallRecvMsgSize": "10000000", - "MaxCallSendMsgSize": "10000000", - "Password": "doe", - "PermitWithoutStream": "false", - "RejectOldCluster": "false", - "Username": "john" - }, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "5s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "5s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "reverse_proxy", + "upstreams": [ + { + "dial": "127.0.0.1:9000" + } + ] + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/not-modified" + ] + } + ] }, { - "body": "Hello etcd", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/etcd" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "15s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "headers", + "response": { + "set": { + "Content-Type": [ + "text/html" + ] + } + } + }, + { + "body": "\u003ch1\u003eESI INCLUDE\u003c/h1\u003e", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/esi-include" + ] + } + ] }, { - "handler": "headers", - "response": { - "set": { - "Vary": [ - "X-Something" - ] - } - } + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": true, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "127.0.0.1:6379" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "5s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "body": "Hello redis url", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/redis-url" + ] + } + ] }, { - "body": "Hello {http.request.header.X-Something}", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/vary" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "reverse_proxy", + "upstreams": [ + { + "dial": "127.0.0.1:81" + } + ] + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/stream" + ] + } + ] }, { - "encodings": { - "gzip": {} - }, - "handler": "encode", - "minimum_length": 5, - "prefer": [ - "gzip" - ] + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": true, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": { + "Addr": "127.0.0.1:6379", + "ConnMaxIdleTime": 5000000000, + "ConnMaxLifetime": 5000000000, + "DB": 1, + "DialTimeout": 5000000000, + "MaxIdleConns": 100, + "MaxRetries": 1, + "MaxRetryBackoff": 5000000000, + "MinIdleConns": 100, + "MinRetryBackoff": 5000000000, + "Network": "my-network", + "Password": "password", + "PoolFIFO": true, + "PoolSize": 99999, + "PoolTimeout": 10000000000, + "ReadTimeout": 5000000000, + "Username": "user", + "WriteTimeout": 5000000000 + }, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "5s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "body": "Hello redis", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/redis" + ] + } + ] }, { - "handler": "headers", - "response": { - "set": { - "Content-Type": [ - "text/plain" - ] - } - } + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "15s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "headers", + "response": { + "set": { + "Vary": [ + "X-Something" + ] + } + } + }, + { + "body": "Hello {http.request.header.X-Something}", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/vary" + ] + } + ] }, { - "body": "Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip.", - "handler": "static_response" - } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/gzip" - ] - } - ] - }, - { - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "Configuration": { - "API": { - "basepath": "", - "debug": { - "basepath": "", - "enable": false, - "security": false - }, - "prometheus": { - "basepath": "", - "enable": false, - "security": false - }, - "security": { - "basepath": "", - "enable": false, - "secret": "", - "users": null - }, - "souin": { - "basepath": "", - "enable": false, - "security": false - } - }, - "CfgCacheKeys": null, - "DefaultCache": { - "allowed_http_verbs": [], - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "cache_name": "", - "cdn": {}, - "default_cache_control": "", - "distributed": false, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "headers": null, - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "regex": { - "exclude": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" - }, - "LogLevel": "", - "SurrogateKeys": null, - "URLs": null - }, - "badger": { - "configuration": null, - "path": "", - "url": "" - }, - "etcd": { - "configuration": null, - "path": "", - "url": "" - }, - "handler": "cache", - "key": { - "disable_body": false, - "disable_host": false, - "disable_method": false, - "disable_query": false, - "headers": null, - "hide": false - }, - "nuts": { - "configuration": null, - "path": "", - "url": "" - }, - "olric": { - "configuration": null, - "path": "", - "url": "" - }, - "redis": { - "configuration": null, - "path": "", - "url": "" - }, - "stale": "0s", - "timeout": { - "backend": "0s", - "cache": "0s" - }, - "ttl": "0s" + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "encodings": { + "gzip": {} + }, + "handler": "encode", + "minimum_length": 5, + "prefer": [ + "gzip" + ] + }, + { + "handler": "headers", + "response": { + "set": { + "Content-Type": [ + "text/plain" + ] + } + } + }, + { + "body": "Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip. Hello, gzip.", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/gzip" + ] + } + ] }, { - "handler": "headers", - "response": { - "set": { - "Content-Type": [ - "text/html" - ] - } - } + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "Configuration": { + "API": { + "basepath": "", + "debug": { + "basepath": "", + "enable": false, + "security": false + }, + "prometheus": { + "basepath": "", + "enable": false, + "security": false + }, + "security": { + "basepath": "", + "enable": false, + "secret": "", + "users": null + }, + "souin": { + "basepath": "", + "enable": false, + "security": false + } + }, + "DefaultCache": { + "allowed_http_verbs": [], + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "cache_name": "", + "cdn": {}, + "default_cache_control": "", + "distributed": false, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "headers": null, + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "regex": { + "exclude": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + "LogLevel": "", + "SurrogateKeys": null, + "URLs": null, + "cache_keys": {} + }, + "badger": { + "configuration": null, + "path": "", + "url": "" + }, + "etcd": { + "configuration": null, + "path": "", + "url": "" + }, + "handler": "cache", + "key": {}, + "nuts": { + "configuration": null, + "path": "", + "url": "" + }, + "olric": { + "configuration": null, + "path": "", + "url": "" + }, + "redis": { + "configuration": null, + "path": "", + "url": "" + }, + "stale": "0s", + "timeout": { + "backend": "0s", + "cache": "0s" + }, + "ttl": "0s" + }, + { + "handler": "headers", + "response": { + "set": { + "Content-Type": [ + "text/html" + ] + } + } + }, + { + "body": "\u003cesi:include src=\"http://localhost:4443/esi-include\" alt=http://localhost:4443/alt-esi-include /\u003e", + "handler": "static_response" + } + ] + } + ] + } + ], + "match": [ + { + "path": [ + "/esi" + ] + } + ] }, { - "body": "", - "handler": "static_response" + "handle": [ + { + "body": "Hello World!", + "handler": "static_response" + } + ] } - ] - } - ] - } - ], - "match": [ - { - "path": [ - "/esi" - ] - } - ] - }, - { - "handle": [ - { - "body": "Hello World!", - "handler": "static_response" + ] } - ] } - ] } - } - } - }, - "logging": { - "logs": { - "default": { - "level": "debug" - } + }, + "logging": { + "logs": { + "default": { + "level": "debug" + } + } } - } } \ No newline at end of file diff --git a/plugins/caddy/go.mod b/plugins/caddy/go.mod index 77be04ecd..72fb2cacf 100644 --- a/plugins/caddy/go.mod +++ b/plugins/caddy/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/buraksezer/olric v0.5.4 github.com/caddyserver/caddy/v2 v2.6.4 - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 go.uber.org/zap v1.24.0 ) @@ -178,4 +178,4 @@ require ( howett.net/plist v1.0.0 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/caddy/httpcache.go b/plugins/caddy/httpcache.go index d034c66d8..4808306b3 100644 --- a/plugins/caddy/httpcache.go +++ b/plugins/caddy/httpcache.go @@ -3,7 +3,6 @@ package httpcache import ( "fmt" "net/http" - "regexp" "time" "github.com/buraksezer/olric/config" @@ -37,7 +36,7 @@ type SouinCaddyMiddleware struct { *middleware.SouinBaseHandler logger *zap.Logger Configuration *Configuration - cacheKeys map[configurationtypes.RegValue]configurationtypes.Key + cacheKeys configurationtypes.CacheKeys // Logger level, fallback on caddy's one when not redefined. LogLevel string `json:"log_level,omitempty"` // Allowed HTTP verbs to be cached by the system. @@ -49,7 +48,7 @@ type SouinCaddyMiddleware struct { // Configure the global key generation. Key configurationtypes.Key `json:"key,omitempty"` // Override the cache key generation matching the pattern. - CacheKeys map[string]configurationtypes.Key `json:"cache_keys,omitempty"` + CacheKeys configurationtypes.CacheKeys `json:"cache_keys,omitempty"` // Configure the Badger cache storage. Nuts configurationtypes.CacheProvider `json:"nuts,omitempty"` // Enable the Etcd distributed cache storage. @@ -106,7 +105,7 @@ func (s *SouinCaddyMiddleware) configurationPropertyMapper() error { } if s.Configuration == nil { s.Configuration = &Configuration{ - cacheKeys: s.cacheKeys, + CacheKeys: s.cacheKeys, DefaultCache: defaultCache, LogLevel: s.LogLevel, } @@ -142,14 +141,19 @@ func (s *SouinCaddyMiddleware) FromApp(app *SouinApp) error { } return nil } - if s.Configuration.cacheKeys == nil { - s.Configuration.cacheKeys = make(map[configurationtypes.RegValue]configurationtypes.Key) + if s.Configuration.CacheKeys == nil || len(s.Configuration.CacheKeys) == 0 { + s.Configuration.CacheKeys = configurationtypes.CacheKeys{} } if s.CacheKeys == nil { s.CacheKeys = app.CacheKeys } - for k, v := range s.CacheKeys { - s.Configuration.cacheKeys[configurationtypes.RegValue{Regexp: regexp.MustCompile(k)}] = v + for _, cacheKey := range s.Configuration.CacheKeys { + for k, v := range cacheKey { + s.Configuration.CacheKeys = append( + s.Configuration.CacheKeys, + map[configurationtypes.RegValue]configurationtypes.Key{k: v}, + ) + } } dc := s.Configuration.DefaultCache @@ -225,6 +229,14 @@ func (s *SouinCaddyMiddleware) Provision(ctx caddy.Context) error { return err } + /* + s.cacheKeys = s.Configuration.cacheKeys + for _, cacheKey := range s.Configuration.CacheKeys { + for k, v := range cacheKey { + s.cacheKeys = append(s.cacheKeys, map[configurationtypes.RegValue]configurationtypes.Key{k: v}) + } + } + */ bh := middleware.NewHTTPCacheHandler(s.Configuration) surrogates, ok := up.LoadOrStore(surrogate_key, bh.SurrogateKeyStorer) if ok { @@ -310,7 +322,7 @@ func parseCaddyfileGlobalOption(h *caddyfile.Dispenser, _ interface{}) (interfac souinApp.DefaultCache = cfg.DefaultCache souinApp.API = cfg.API - souinApp.CacheKeys = cfg.CfgCacheKeys + souinApp.CacheKeys = cfg.CacheKeys souinApp.LogLevel = cfg.LogLevel return httpcaddyfile.App{ @@ -329,8 +341,9 @@ func (s *SouinCaddyMiddleware) UnmarshalCaddyfile(h *caddyfile.Dispenser) error s.Configuration = &Configuration{ DefaultCache: &dc, } + err := parseConfiguration(s.Configuration, h, false) - return parseConfiguration(s.Configuration, h, false) + return err } // Interface guards diff --git a/plugins/chi/go.mod b/plugins/chi/go.mod index b9a3b6ef4..c177ba860 100644 --- a/plugins/chi/go.mod +++ b/plugins/chi/go.mod @@ -3,7 +3,7 @@ module github.com/darkweak/souin/plugins/chi go 1.19 require ( - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 github.com/go-chi/chi/v5 v5.0.8 ) @@ -83,4 +83,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/dotweb/go.mod b/plugins/dotweb/go.mod index 314fbb157..bdce33f65 100644 --- a/plugins/dotweb/go.mod +++ b/plugins/dotweb/go.mod @@ -3,7 +3,7 @@ module github.com/darkweak/souin/plugins/dotweb go 1.19 require ( - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 github.com/devfeel/dotweb v1.7.19 ) @@ -84,4 +84,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/echo/go.mod b/plugins/echo/go.mod index 57ba3be58..5b6425541 100644 --- a/plugins/echo/go.mod +++ b/plugins/echo/go.mod @@ -3,7 +3,7 @@ module github.com/darkweak/souin/plugins/echo go 1.19 require ( - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 github.com/labstack/echo/v4 v4.10.2 ) @@ -89,4 +89,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/fiber/go.mod b/plugins/fiber/go.mod index 15d59859f..37e5a1678 100644 --- a/plugins/fiber/go.mod +++ b/plugins/fiber/go.mod @@ -3,7 +3,7 @@ module github.com/darkweak/souin/plugins/fiber go 1.19 require ( - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 github.com/gofiber/fiber/v2 v2.42.0 github.com/valyala/fasthttp v1.44.0 ) @@ -95,4 +95,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/gin/go.mod b/plugins/gin/go.mod index 5aa80feb3..94d56e94f 100644 --- a/plugins/gin/go.mod +++ b/plugins/gin/go.mod @@ -3,7 +3,7 @@ module github.com/darkweak/souin/plugins/gin go 1.19 require ( - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 github.com/gin-gonic/gin v1.9.0 ) @@ -101,4 +101,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/go-zero/go.mod b/plugins/go-zero/go.mod index cc502bca9..981d09a76 100644 --- a/plugins/go-zero/go.mod +++ b/plugins/go-zero/go.mod @@ -3,7 +3,7 @@ module github.com/darkweak/souin/plugins/go-zero go 1.19 require ( - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 github.com/zeromicro/go-zero v1.5.0 ) @@ -107,4 +107,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/goyave/go.mod b/plugins/goyave/go.mod index 021282aa9..1b12bd2ea 100644 --- a/plugins/goyave/go.mod +++ b/plugins/goyave/go.mod @@ -3,7 +3,7 @@ module github.com/darkweak/souin/plugins/goyave go 1.19 require ( - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 goyave.dev/goyave/v4 v4.4.8 ) @@ -90,4 +90,4 @@ require ( gorm.io/gorm v1.24.6 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/kratos/configuration.go b/plugins/kratos/configuration.go index d54d341b3..bc6f40aec 100644 --- a/plugins/kratos/configuration.go +++ b/plugins/kratos/configuration.go @@ -88,8 +88,8 @@ func parseAPI(apiConfiguration map[string]config.Value) configurationtypes.API { return a } -func parseCacheKeys(ccConfiguration map[string]config.Value) map[configurationtypes.RegValue]configurationtypes.Key { - cacheKeys := make(map[configurationtypes.RegValue]configurationtypes.Key) +func parseCacheKeys(ccConfiguration map[string]config.Value) configurationtypes.CacheKeys { + cacheKeys := make(configurationtypes.CacheKeys, 0) for cacheKeysConfigurationK, cacheKeysConfigurationV := range ccConfiguration { ck := configurationtypes.Key{} cacheKeysConfigurationVMap, _ := cacheKeysConfigurationV.Map() @@ -114,7 +114,7 @@ func parseCacheKeys(ccConfiguration map[string]config.Value) map[configurationty } } rg := regexp.MustCompile(cacheKeysConfigurationK) - cacheKeys[configurationtypes.RegValue{Regexp: rg}] = ck + cacheKeys = append(cacheKeys, configurationtypes.CacheKey{{Regexp: rg}: ck}) } return cacheKeys diff --git a/plugins/kratos/go.mod b/plugins/kratos/go.mod index f7e1d43cf..43b4b53fe 100644 --- a/plugins/kratos/go.mod +++ b/plugins/kratos/go.mod @@ -3,7 +3,7 @@ module github.com/darkweak/souin/plugins/kratos go 1.19 require ( - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 github.com/go-kratos/kratos/v2 v2.5.4 gopkg.in/yaml.v3 v3.0.1 ) @@ -86,4 +86,4 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/roadrunner/go.mod b/plugins/roadrunner/go.mod index 768d4516f..291eee474 100644 --- a/plugins/roadrunner/go.mod +++ b/plugins/roadrunner/go.mod @@ -3,7 +3,7 @@ module github.com/darkweak/souin/plugins/roadrunner go 1.19 require ( - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 github.com/roadrunner-server/errors v1.2.0 go.uber.org/zap v1.24.0 gopkg.in/yaml.v3 v3.0.1 @@ -83,4 +83,4 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/skipper/go.mod b/plugins/skipper/go.mod index 7a4dfa56c..3dcb517d4 100644 --- a/plugins/skipper/go.mod +++ b/plugins/skipper/go.mod @@ -3,7 +3,7 @@ module github.com/darkweak/souin/plugins/skipper go 1.19 require ( - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 github.com/zalando/skipper v0.13.225 ) @@ -127,4 +127,4 @@ require ( layeh.com/gopher-json v0.0.0-20201124131017-552bb3c4c3bf // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/souin/agnostic/configuration_parser.go b/plugins/souin/agnostic/configuration_parser.go index d8cabd4f9..7526904a1 100644 --- a/plugins/souin/agnostic/configuration_parser.go +++ b/plugins/souin/agnostic/configuration_parser.go @@ -55,8 +55,8 @@ func parseAPI(apiConfiguration map[string]interface{}) configurationtypes.API { return a } -func parseCacheKeys(ccConfiguration map[string]interface{}) map[configurationtypes.RegValue]configurationtypes.Key { - cacheKeys := make(map[configurationtypes.RegValue]configurationtypes.Key) +func parseCacheKeys(ccConfiguration map[string]interface{}) configurationtypes.CacheKeys { + cacheKeys := make(configurationtypes.CacheKeys, 0) for cacheKeysConfigurationK, cacheKeysConfigurationV := range ccConfiguration { ck := configurationtypes.Key{} for cacheKeysConfigurationVMapK, cacheKeysConfigurationVMapV := range cacheKeysConfigurationV.(map[string]interface{}) { @@ -82,7 +82,7 @@ func parseCacheKeys(ccConfiguration map[string]interface{}) map[configurationtyp } } rg := regexp.MustCompile(cacheKeysConfigurationK) - cacheKeys[configurationtypes.RegValue{Regexp: rg}] = ck + cacheKeys = append(cacheKeys, configurationtypes.CacheKey{{Regexp: rg}: ck}) } return cacheKeys diff --git a/plugins/souin/configuration/configuration.go b/plugins/souin/configuration/configuration.go index 0aacd3028..cb78e7c6a 100644 --- a/plugins/souin/configuration/configuration.go +++ b/plugins/souin/configuration/configuration.go @@ -9,15 +9,15 @@ import ( "gopkg.in/yaml.v3" ) -//Configuration holder +// Configuration holder type Configuration struct { - DefaultCache *configurationtypes.DefaultCache `yaml:"default_cache"` - CacheKeys map[configurationtypes.RegValue]configurationtypes.Key `yaml:"cache_keys"` - API configurationtypes.API `yaml:"api"` - ReverseProxyURL string `yaml:"reverse_proxy_url"` - SSLProviders []string `yaml:"ssl_providers"` - URLs map[string]configurationtypes.URL `yaml:"urls"` - LogLevel string `yaml:"log_level"` + DefaultCache *configurationtypes.DefaultCache `yaml:"default_cache"` + CacheKeys configurationtypes.CacheKeys `yaml:"cache_keys"` + API configurationtypes.API `yaml:"api"` + ReverseProxyURL string `yaml:"reverse_proxy_url"` + SSLProviders []string `yaml:"ssl_providers"` + URLs map[string]configurationtypes.URL `yaml:"urls"` + LogLevel string `yaml:"log_level"` logger *zap.Logger Ykeys map[string]configurationtypes.SurrogateKeys `yaml:"ykeys"` SurrogateKeys map[string]configurationtypes.SurrogateKeys `yaml:"surrogate_keys"` @@ -90,7 +90,7 @@ func (c *Configuration) GetSurrogateKeys() map[string]configurationtypes.Surroga } // GetCacheKeys get the cache keys rules to override -func (c *Configuration) GetCacheKeys() map[configurationtypes.RegValue]configurationtypes.Key { +func (c *Configuration) GetCacheKeys() configurationtypes.CacheKeys { return c.CacheKeys } diff --git a/plugins/souin/configuration/configuration.yml b/plugins/souin/configuration/configuration.yml index ed7671a4b..1376a611c 100644 --- a/plugins/souin/configuration/configuration.yml +++ b/plugins/souin/configuration/configuration.yml @@ -4,5 +4,10 @@ default_cache: regex: exclude: /excluded ttl: 5s +cache_keys: + .+: + disable_body: true + disable_url: false + disable_query: true log_level: debug reverse_proxy_url: 'http://traefik' diff --git a/plugins/souin/main.go b/plugins/souin/main.go index 497fc4921..c06a2b2d9 100644 --- a/plugins/souin/main.go +++ b/plugins/souin/main.go @@ -40,6 +40,7 @@ func startServer(config *tls.Config, port string) (net.Listener, *http.Server) { func main() { c := configuration.GetConfiguration() + fmt.Printf("%+v\n\n", c) configChannel := make(chan int) tlsConfig := &tls.Config{ Certificates: make([]tls.Certificate, 0), diff --git a/plugins/traefik/configuration.go b/plugins/traefik/configuration.go index 5012c20a7..32386dc22 100644 --- a/plugins/traefik/configuration.go +++ b/plugins/traefik/configuration.go @@ -5,13 +5,13 @@ import ( "go.uber.org/zap" ) -//Configuration holder +// Configuration holder type Configuration struct { - DefaultCache *configurationtypes.DefaultCache `json:"default_cache" yaml:"default_cache"` - API configurationtypes.API `json:"api" yaml:"api"` - CacheKeys map[configurationtypes.RegValue]configurationtypes.Key `yaml:"cache_keys"` - URLs map[string]configurationtypes.URL `json:"urls" yaml:"urls"` - LogLevel string `json:"log_level" yaml:"log_level"` + DefaultCache *configurationtypes.DefaultCache `json:"default_cache" yaml:"default_cache"` + API configurationtypes.API `json:"api" yaml:"api"` + CacheKeys configurationtypes.CacheKeys `yaml:"cache_keys"` + URLs map[string]configurationtypes.URL `json:"urls" yaml:"urls"` + LogLevel string `json:"log_level" yaml:"log_level"` Logger *zap.Logger Ykeys map[string]configurationtypes.SurrogateKeys `json:"ykeys" yaml:"ykeys"` SurrogateKeys map[string]configurationtypes.SurrogateKeys `json:"surrogate_keys" yaml:"surrogate_keys"` @@ -58,7 +58,7 @@ func (c *Configuration) GetSurrogateKeys() map[string]configurationtypes.Surroga } // GetCacheKeys get the cache keys rules to override -func (c *Configuration) GetCacheKeys() map[configurationtypes.RegValue]configurationtypes.Key { +func (c *Configuration) GetCacheKeys() configurationtypes.CacheKeys { return c.CacheKeys } diff --git a/plugins/traefik/docker-compose.yml.test b/plugins/traefik/docker-compose.yml.test index c51bfad76..6d98deeea 100644 --- a/plugins/traefik/docker-compose.yml.test +++ b/plugins/traefik/docker-compose.yml.test @@ -2,7 +2,7 @@ version: '3.4' services: traefik: - image: traefik:v2.9.8 + image: traefik:v3.0 volumes: - /var/run/docker.sock:/var/run/docker.sock - ../..:/plugins-local/src/github.com/darkweak/souin diff --git a/plugins/traefik/go.mod b/plugins/traefik/go.mod index da9dc0336..bf5c3b89e 100644 --- a/plugins/traefik/go.mod +++ b/plugins/traefik/go.mod @@ -3,7 +3,8 @@ module github.com/darkweak/souin/plugins/traefik go 1.19 require ( - github.com/darkweak/souin v1.6.35 + github.com/akyoto/cache v1.0.6 + github.com/darkweak/souin v1.6.36 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pquerna/cachecontrol v0.1.0 go.uber.org/zap v1.21.0 @@ -85,4 +86,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/traefik/go.sum b/plugins/traefik/go.sum index 3972ebdb3..8fd6b5d27 100644 --- a/plugins/traefik/go.sum +++ b/plugins/traefik/go.sum @@ -524,6 +524,8 @@ github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/akyoto/cache v1.0.6 h1:5XGVVYoi2i+DZLLPuVIXtsNIJ/qaAM16XT0LaBaXd2k= +github.com/akyoto/cache v1.0.6/go.mod h1:WfxTRqKhfgAG71Xh6E3WLpjhBtZI37O53G4h5s+3iM4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= diff --git a/plugins/traefik/main.go b/plugins/traefik/main.go index 2ca9ae7f4..9610855f3 100644 --- a/plugins/traefik/main.go +++ b/plugins/traefik/main.go @@ -3,6 +3,7 @@ package traefik import ( "context" "encoding/json" + "fmt" "net/http" "strings" "time" @@ -223,6 +224,7 @@ func New(_ context.Context, next http.Handler, config *TestConfiguration, name s } func (s *SouinTraefikMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + fmt.Printf("%+v\n", s.SouinBaseHandler) _ = s.SouinBaseHandler.ServeHTTP(rw, req, func(w http.ResponseWriter, r *http.Request) error { s.next.ServeHTTP(w, r) diff --git a/plugins/traefik/override/context/key.go b/plugins/traefik/override/context/key.go index edd32d9e6..ca09baaaf 100644 --- a/plugins/traefik/override/context/key.go +++ b/plugins/traefik/override/context/key.go @@ -21,7 +21,7 @@ type keyContext struct { disable_query bool displayable bool headers []string - overrides map[*regexp.Regexp]keyContext + overrides []map[*regexp.Regexp]keyContext } func (g *keyContext) SetupContext(c configurationtypes.AbstractConfigurationInterface) { @@ -29,19 +29,22 @@ func (g *keyContext) SetupContext(c configurationtypes.AbstractConfigurationInte g.disable_body = k.DisableBody g.disable_host = k.DisableHost g.disable_method = k.DisableMethod + g.disable_query = k.DisableQuery g.displayable = !k.Hide g.headers = k.Headers - g.overrides = make(map[*regexp.Regexp]keyContext) - - for r, v := range c.GetCacheKeys() { - g.overrides[r.Regexp] = keyContext{ - disable_body: v.DisableBody, - disable_host: v.DisableHost, - disable_method: v.DisableMethod, - disable_query: v.DisableQuery, - displayable: v.Hide, - headers: v.Headers, + g.overrides = make([]map[*regexp.Regexp]keyContext, 0) + + for _, cacheKey := range c.GetCacheKeys() { + for r, v := range cacheKey { + g.overrides = append(g.overrides, map[*regexp.Regexp]keyContext{r.Regexp: { + disable_body: v.DisableBody, + disable_host: v.DisableHost, + disable_method: v.DisableMethod, + disable_query: v.DisableQuery, + displayable: !v.Hide, + headers: v.Headers, + }}) } } } @@ -54,6 +57,7 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { if req.TLS != nil { scheme = "https-" } + query := "" body := "" host := "" method := "" @@ -61,7 +65,7 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { displayable := g.displayable if !g.disable_query && len(req.URL.RawQuery) > 0 { - key += "?" + req.URL.RawQuery + query += "?" + req.URL.RawQuery } if !g.disable_body { @@ -81,27 +85,39 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { headerValues += "-" + req.Header.Get(hn) } - for k, v := range g.overrides { - if k.MatchString(req.RequestURI) { - displayable = v.displayable - host = "" - method = "" - if !v.disable_body { - body = req.Context().Value(HashBody).(string) - } - if !v.disable_method { - method = req.Method + "-" - } - if !v.disable_host { - host = req.Host + "-" - } - if len(v.headers) > 0 { - headerValues = "" - for _, hn := range v.headers { - headers = v.headers - headerValues += "-" + req.Header.Get(hn) + hasOverride := false + for _, current := range g.overrides { + for k, v := range current { + if k.MatchString(req.RequestURI) { + displayable = v.displayable + host = "" + method = "" + query = "" + if !v.disable_query && len(req.URL.RawQuery) > 0 { + query = "?" + req.URL.RawQuery + } + if !v.disable_body { + body = req.Context().Value(HashBody).(string) } + if !v.disable_method { + method = req.Method + "-" + } + if !v.disable_host { + host = req.Host + "-" + } + if len(v.headers) > 0 { + headerValues = "" + for _, hn := range v.headers { + headers = v.headers + headerValues += "-" + req.Header.Get(hn) + } + } + hasOverride = true + break } + } + + if hasOverride { break } } @@ -112,7 +128,7 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { context.WithValue( req.Context(), Key, - method+scheme+host+key+body+headerValues, + method+scheme+host+key+query+body+headerValues, ), IgnoredHeaders, headers, diff --git a/plugins/traefik/override/storage/cacheProvider.go b/plugins/traefik/override/storage/cacheProvider.go index 6afa7a762..b11a0b44c 100644 --- a/plugins/traefik/override/storage/cacheProvider.go +++ b/plugins/traefik/override/storage/cacheProvider.go @@ -6,8 +6,8 @@ import ( "strings" "time" + "github.com/akyoto/cache" t "github.com/darkweak/souin/configurationtypes" - "github.com/patrickmn/go-cache" ) // Cache provider type @@ -18,17 +18,17 @@ type Cache struct { // CacheConnectionFactory function create new Cache instance func CacheConnectionFactory(c t.AbstractConfigurationInterface) (Storer, error) { - provider := cache.New(1*time.Second, 1*time.Second) + provider := cache.New(1 * time.Second) return &Cache{Cache: provider, stale: c.GetDefaultCache().GetStale()}, nil } // ListKeys method returns the list of existing keys func (provider *Cache) ListKeys() []string { - items := provider.Items() - keys := make([]string, 0, len(items)) - for k := range items { - keys = append(keys, k) - } + var keys []string + provider.Cache.Range(func(key, _ interface{}) bool { + keys = append(keys, key.(string)) + return true + }) return keys } @@ -47,20 +47,23 @@ func (provider *Cache) Get(key string) []byte { // Prefix method returns the populated response if exists, empty response then func (provider *Cache) Prefix(key string, req *http.Request) []byte { var result []byte - - for k, v := range provider.Items() { + provider.Cache.Range(func(k, v interface{}) bool { if k == key { - return v.Object.([]byte) + result = v.([]byte) + return false } - if !strings.HasPrefix(k, key) { - continue + if !strings.HasPrefix(k.(string), key) { + return true } - if varyVoter(key, req, k) { - result = v.Object.([]byte) + if varyVoter(key, req, k.(string)) { + result = v.([]byte) + return false } - } + + return true + }) return result } @@ -90,11 +93,12 @@ func (provider *Cache) DeleteMany(key string) { return } - for k := range provider.Items() { - if re.MatchString(k) { - provider.Delete(k) + provider.Cache.Range(func(k, _ interface{}) bool { + if re.MatchString(k.(string)) { + provider.Delete(k.(string)) } - } + return true + }) } // Init method will @@ -104,7 +108,7 @@ func (provider *Cache) Init() error { // Reset method will reset or close provider func (provider *Cache) Reset() error { - provider.Cache.Flush() + provider.DeleteMany("*") return nil } diff --git a/plugins/traefik/vendor/github.com/akyoto/cache/.drone.yml b/plugins/traefik/vendor/github.com/akyoto/cache/.drone.yml new file mode 100644 index 000000000..ec0142046 --- /dev/null +++ b/plugins/traefik/vendor/github.com/akyoto/cache/.drone.yml @@ -0,0 +1,21 @@ +kind: pipeline +name: default + +steps: +- name: test + image: golang + commands: + - go version + - go get ./... + - go build ./... + - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.23.6 + - golangci-lint run --enable dupl --enable goconst --enable gocritic --enable misspell --enable prealloc --enable unconvert --enable unparam + - go test -v -race -coverprofile=coverage.txt ./... + +- name: coverage + image: plugins/codecov + settings: + token: + from_secret: codecov-token + files: + - coverage.txt \ No newline at end of file diff --git a/plugins/traefik/vendor/github.com/akyoto/cache/.gitignore b/plugins/traefik/vendor/github.com/akyoto/cache/.gitignore new file mode 100644 index 000000000..39b3c4820 --- /dev/null +++ b/plugins/traefik/vendor/github.com/akyoto/cache/.gitignore @@ -0,0 +1,7 @@ +*.exe +*.exe~ +*.dll +*.so +*.dylib +*.test +*.out diff --git a/plugins/traefik/vendor/github.com/akyoto/cache/Cache.go b/plugins/traefik/vendor/github.com/akyoto/cache/Cache.go new file mode 100644 index 000000000..b6d096e18 --- /dev/null +++ b/plugins/traefik/vendor/github.com/akyoto/cache/Cache.go @@ -0,0 +1,114 @@ +package cache + +import ( + "sync" + "time" +) + +// Cache stores arbitrary data with expiration time. +type Cache struct { + items sync.Map + close chan struct{} +} + +// An item represents arbitrary data with expiration time. +type item struct { + data interface{} + expires int64 +} + +// New creates a new cache that asynchronously cleans +// expired entries after the given time passes. +func New(cleaningInterval time.Duration) *Cache { + cache := &Cache{ + close: make(chan struct{}), + } + + go func() { + ticker := time.NewTicker(cleaningInterval) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + now := time.Now().UnixNano() + + cache.items.Range(func(key, value interface{}) bool { + item := value.(item) + + if item.expires > 0 && now > item.expires { + cache.items.Delete(key) + } + + return true + }) + + case <-cache.close: + return + } + } + }() + + return cache +} + +// Get gets the value for the given key. +func (cache *Cache) Get(key interface{}) (interface{}, bool) { + obj, exists := cache.items.Load(key) + + if !exists { + return nil, false + } + + item := obj.(item) + + if item.expires > 0 && time.Now().UnixNano() > item.expires { + return nil, false + } + + return item.data, true +} + +// Set sets a value for the given key with an expiration duration. +// If the duration is 0 or less, it will be stored forever. +func (cache *Cache) Set(key interface{}, value interface{}, duration time.Duration) { + var expires int64 + + if duration > 0 { + expires = time.Now().Add(duration).UnixNano() + } + + cache.items.Store(key, item{ + data: value, + expires: expires, + }) +} + +// Range calls f sequentially for each key and value present in the cache. +// If f returns false, range stops the iteration. +func (cache *Cache) Range(f func(key, value interface{}) bool) { + now := time.Now().UnixNano() + + fn := func(key, value interface{}) bool { + item := value.(item) + + if item.expires > 0 && now > item.expires { + return true + } + + return f(key, item.data) + } + + cache.items.Range(fn) +} + +// Delete deletes the key and its value from the cache. +func (cache *Cache) Delete(key interface{}) { + cache.items.Delete(key) +} + +// Close closes the cache and frees up resources. +func (cache *Cache) Close() { + cache.close <- struct{}{} + cache.items = sync.Map{} +} diff --git a/plugins/traefik/vendor/github.com/akyoto/cache/LICENSE b/plugins/traefik/vendor/github.com/akyoto/cache/LICENSE new file mode 100644 index 000000000..6432f74e0 --- /dev/null +++ b/plugins/traefik/vendor/github.com/akyoto/cache/LICENSE @@ -0,0 +1,18 @@ +Sponsorship License + +Copyright (c) 2019 Eduard Urbach + +* You are permitted to use the software freely for non-commercial purposes. +* You MUST be a sponsor donating at least 10 USD every month to me if you use the software for commercial purposes. + +To become a sponsor: + +1. Visit the following page: https://github.com/users/akyoto/sponsorship +2. Register as a sponsor for the 10 USD per month tier. + +Additional notes: + +* Canceling your sponsorship will also revoke the rights to use the software for commercial purposes. +* The software is provided "as is", without warranty of any kind. +* The above copyright notice and this permission must be included in all copies of the software. + diff --git a/plugins/traefik/vendor/github.com/akyoto/cache/README.md b/plugins/traefik/vendor/github.com/akyoto/cache/README.md new file mode 100644 index 000000000..debba58d5 --- /dev/null +++ b/plugins/traefik/vendor/github.com/akyoto/cache/README.md @@ -0,0 +1,62 @@ +# cache + +[![Godoc][godoc-image]][godoc-url] +[![Report][report-image]][report-url] +[![Tests][tests-image]][tests-url] +[![Coverage][coverage-image]][coverage-url] +[![Sponsor][sponsor-image]][sponsor-url] + +Cache arbitrary data with an expiration time. + +## Features + +* 0 dependencies +* About 100 lines of code +* 100% test coverage + +## Usage + +```go +// New cache +c := cache.New(5 * time.Minute) + +// Put something into the cache +c.Set("a", "b", 1 * time.Minute) + +// Read from the cache +obj, found := c.Get("a") + +// Convert the type +fmt.Println(obj.(string)) +``` + +## Benchmarks + +```text +BenchmarkGet-12 300000000 3.88 ns/op 0 B/op 0 allocs/op +BenchmarkSet-12 10000000 183 ns/op 48 B/op 2 allocs/op +BenchmarkNew-12 10000000 112 ns/op 352 B/op 5 allocs/op +``` + +## Style + +Please take a look at the [style guidelines](https://github.com/akyoto/quality/blob/master/STYLE.md) if you'd like to make a pull request. + +## Sponsors + +| [![Cedric Fung](https://avatars3.githubusercontent.com/u/2269238?s=70&v=4)](https://github.com/cedricfung) | [![Scott Rayapoullé](https://avatars3.githubusercontent.com/u/11772084?s=70&v=4)](https://github.com/soulcramer) | [![Eduard Urbach](https://avatars3.githubusercontent.com/u/438936?s=70&v=4)](https://eduardurbach.com) | +| --- | --- | --- | +| [Cedric Fung](https://github.com/cedricfung) | [Scott Rayapoullé](https://github.com/soulcramer) | [Eduard Urbach](https://eduardurbach.com) | + +Want to see [your own name here?](https://github.com/users/akyoto/sponsorship) + +[godoc-image]: https://godoc.org/github.com/akyoto/cache?status.svg +[godoc-url]: https://godoc.org/github.com/akyoto/cache +[report-image]: https://goreportcard.com/badge/github.com/akyoto/cache +[report-url]: https://goreportcard.com/report/github.com/akyoto/cache +[tests-image]: https://cloud.drone.io/api/badges/akyoto/cache/status.svg +[tests-url]: https://cloud.drone.io/akyoto/cache +[coverage-image]: https://codecov.io/gh/akyoto/cache/graph/badge.svg +[coverage-url]: https://codecov.io/gh/akyoto/cache +[sponsor-image]: https://img.shields.io/badge/github-donate-green.svg +[sponsor-url]: https://github.com/users/akyoto/sponsorship diff --git a/plugins/traefik/vendor/github.com/akyoto/cache/README.src.md b/plugins/traefik/vendor/github.com/akyoto/cache/README.src.md new file mode 100644 index 000000000..e8d481187 --- /dev/null +++ b/plugins/traefik/vendor/github.com/akyoto/cache/README.src.md @@ -0,0 +1,37 @@ +# {name} + +{go:header} + +Cache arbitrary data with an expiration time. + +## Features + +* 0 dependencies +* About 100 lines of code +* 100% test coverage + +## Usage + +```go +// New cache +c := cache.New(5 * time.Minute) + +// Put something into the cache +c.Set("a", "b", 1 * time.Minute) + +// Read from the cache +obj, found := c.Get("a") + +// Convert the type +fmt.Println(obj.(string)) +``` + +## Benchmarks + +```text +BenchmarkGet-12 300000000 3.88 ns/op 0 B/op 0 allocs/op +BenchmarkSet-12 10000000 183 ns/op 48 B/op 2 allocs/op +BenchmarkNew-12 10000000 112 ns/op 352 B/op 5 allocs/op +``` + +{go:footer} diff --git a/plugins/traefik/vendor/github.com/darkweak/souin/configurationtypes/types.go b/plugins/traefik/vendor/github.com/darkweak/souin/configurationtypes/types.go index 45d9f5f8a..d829b5f1c 100644 --- a/plugins/traefik/vendor/github.com/darkweak/souin/configurationtypes/types.go +++ b/plugins/traefik/vendor/github.com/darkweak/souin/configurationtypes/types.go @@ -1,14 +1,106 @@ package configurationtypes import ( + "bytes" "encoding/json" + "fmt" "regexp" + "strconv" + "strings" "time" "go.uber.org/zap" yaml "gopkg.in/yaml.v3" ) +type CacheKey map[RegValue]Key +type CacheKeys []CacheKey + +func (c *CacheKeys) parseJSON(rootDecoder *json.Decoder) { + var token json.Token + var err error + + _, _ = rootDecoder.Token() + _, _ = rootDecoder.Token() + _, _ = rootDecoder.Token() + + for err == nil { + token, err = rootDecoder.Token() + key := Key{} + rg := fmt.Sprint(token) + + value := fmt.Sprint(token) + if value == "}" || token == nil { + continue + } + for value != "}" && token != nil { + token, _ = rootDecoder.Token() + value = fmt.Sprint(token) + switch value { + case "disable_body": + val, _ := rootDecoder.Token() + key.DisableBody, _ = strconv.ParseBool(fmt.Sprint(val)) + case "disable_host": + val, _ := rootDecoder.Token() + key.DisableHost, _ = strconv.ParseBool(fmt.Sprint(val)) + case "disable_method": + val, _ := rootDecoder.Token() + key.DisableMethod, _ = strconv.ParseBool(fmt.Sprint(val)) + case "disable_query": + val, _ := rootDecoder.Token() + key.DisableQuery, _ = strconv.ParseBool(fmt.Sprint(val)) + case "hide": + val, _ := rootDecoder.Token() + key.Hide, _ = strconv.ParseBool(fmt.Sprint(val)) + case "headers": + val, _ := rootDecoder.Token() + key.Headers = []string{} + for fmt.Sprint(val) != "]" { + val, _ = rootDecoder.Token() + header := fmt.Sprint(val) + if header != "]" { + key.Headers = append(key.Headers, header) + } + } + } + } + *c = append(*c, CacheKey{ + {Regexp: regexp.MustCompile(rg)}: key, + }) + } +} + +func (c *CacheKeys) UnmarshalYAML(value *yaml.Node) error { + for i := 0; i < len(value.Content)/2; i++ { + var cacheKey CacheKey + err := value.Decode(&cacheKey) + if err != nil { + return err + } + *c = append(*c, cacheKey) + } + + return nil +} + +func (c *CacheKeys) UnmarshalJSON(value []byte) error { + c.parseJSON(json.NewDecoder(bytes.NewBuffer(value))) + + return nil +} + +func (c *CacheKeys) MarshalJSON() ([]byte, error) { + var strKeys []string + for _, cacheKey := range *c { + for rg, key := range cacheKey { + keyBytes, _ := json.Marshal(key) + strKeys = append(strKeys, fmt.Sprintf(`"%s": %v`, rg.Regexp.String(), string(keyBytes))) + } + } + + return []byte(fmt.Sprintf(`{%s}`, strings.Join(strKeys, ","))), nil +} + // Duration is the super object to wrap the duration and be able to parse it from the configuration type Duration struct { time.Duration @@ -112,12 +204,12 @@ type CDN struct { } type Key struct { - DisableBody bool `json:"disable_body" yaml:"disable_body"` - DisableHost bool `json:"disable_host" yaml:"disable_host"` - DisableMethod bool `json:"disable_method" yaml:"disable_method"` - DisableQuery bool `json:"disable_query" yaml:"disable_query"` - Hide bool `json:"hide" yaml:"hide"` - Headers []string `json:"headers" yaml:"headers"` + DisableBody bool `json:"disable_body,omitempty" yaml:"disable_body,omitempty"` + DisableHost bool `json:"disable_host,omitempty" yaml:"disable_host,omitempty"` + DisableMethod bool `json:"disable_method,omitempty" yaml:"disable_method,omitempty"` + DisableQuery bool `json:"disable_query,omitempty" yaml:"disable_query,omitempty"` + Hide bool `json:"hide,omitempty" yaml:"hide,omitempty"` + Headers []string `json:"headers,omitempty" yaml:"headers,omitempty"` } // DefaultCache configuration @@ -287,5 +379,5 @@ type AbstractConfigurationInterface interface { SetLogger(*zap.Logger) GetYkeys() map[string]SurrogateKeys GetSurrogateKeys() map[string]SurrogateKeys - GetCacheKeys() map[RegValue]Key + GetCacheKeys() CacheKeys } diff --git a/plugins/traefik/vendor/github.com/darkweak/souin/context/key.go b/plugins/traefik/vendor/github.com/darkweak/souin/context/key.go index edd32d9e6..ca09baaaf 100644 --- a/plugins/traefik/vendor/github.com/darkweak/souin/context/key.go +++ b/plugins/traefik/vendor/github.com/darkweak/souin/context/key.go @@ -21,7 +21,7 @@ type keyContext struct { disable_query bool displayable bool headers []string - overrides map[*regexp.Regexp]keyContext + overrides []map[*regexp.Regexp]keyContext } func (g *keyContext) SetupContext(c configurationtypes.AbstractConfigurationInterface) { @@ -29,19 +29,22 @@ func (g *keyContext) SetupContext(c configurationtypes.AbstractConfigurationInte g.disable_body = k.DisableBody g.disable_host = k.DisableHost g.disable_method = k.DisableMethod + g.disable_query = k.DisableQuery g.displayable = !k.Hide g.headers = k.Headers - g.overrides = make(map[*regexp.Regexp]keyContext) - - for r, v := range c.GetCacheKeys() { - g.overrides[r.Regexp] = keyContext{ - disable_body: v.DisableBody, - disable_host: v.DisableHost, - disable_method: v.DisableMethod, - disable_query: v.DisableQuery, - displayable: v.Hide, - headers: v.Headers, + g.overrides = make([]map[*regexp.Regexp]keyContext, 0) + + for _, cacheKey := range c.GetCacheKeys() { + for r, v := range cacheKey { + g.overrides = append(g.overrides, map[*regexp.Regexp]keyContext{r.Regexp: { + disable_body: v.DisableBody, + disable_host: v.DisableHost, + disable_method: v.DisableMethod, + disable_query: v.DisableQuery, + displayable: !v.Hide, + headers: v.Headers, + }}) } } } @@ -54,6 +57,7 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { if req.TLS != nil { scheme = "https-" } + query := "" body := "" host := "" method := "" @@ -61,7 +65,7 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { displayable := g.displayable if !g.disable_query && len(req.URL.RawQuery) > 0 { - key += "?" + req.URL.RawQuery + query += "?" + req.URL.RawQuery } if !g.disable_body { @@ -81,27 +85,39 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { headerValues += "-" + req.Header.Get(hn) } - for k, v := range g.overrides { - if k.MatchString(req.RequestURI) { - displayable = v.displayable - host = "" - method = "" - if !v.disable_body { - body = req.Context().Value(HashBody).(string) - } - if !v.disable_method { - method = req.Method + "-" - } - if !v.disable_host { - host = req.Host + "-" - } - if len(v.headers) > 0 { - headerValues = "" - for _, hn := range v.headers { - headers = v.headers - headerValues += "-" + req.Header.Get(hn) + hasOverride := false + for _, current := range g.overrides { + for k, v := range current { + if k.MatchString(req.RequestURI) { + displayable = v.displayable + host = "" + method = "" + query = "" + if !v.disable_query && len(req.URL.RawQuery) > 0 { + query = "?" + req.URL.RawQuery + } + if !v.disable_body { + body = req.Context().Value(HashBody).(string) } + if !v.disable_method { + method = req.Method + "-" + } + if !v.disable_host { + host = req.Host + "-" + } + if len(v.headers) > 0 { + headerValues = "" + for _, hn := range v.headers { + headers = v.headers + headerValues += "-" + req.Header.Get(hn) + } + } + hasOverride = true + break } + } + + if hasOverride { break } } @@ -112,7 +128,7 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { context.WithValue( req.Context(), Key, - method+scheme+host+key+body+headerValues, + method+scheme+host+key+query+body+headerValues, ), IgnoredHeaders, headers, diff --git a/plugins/traefik/vendor/github.com/darkweak/souin/pkg/middleware/configuration.go b/plugins/traefik/vendor/github.com/darkweak/souin/pkg/middleware/configuration.go index ed8f1825b..b408830b6 100644 --- a/plugins/traefik/vendor/github.com/darkweak/souin/pkg/middleware/configuration.go +++ b/plugins/traefik/vendor/github.com/darkweak/souin/pkg/middleware/configuration.go @@ -7,11 +7,11 @@ import ( // BaseConfiguration holder type BaseConfiguration struct { - DefaultCache *configurationtypes.DefaultCache `json:"default_cache" yaml:"default_cache"` - API configurationtypes.API `json:"api" yaml:"api"` - CacheKeys map[configurationtypes.RegValue]configurationtypes.Key `yaml:"cache_keys"` - URLs map[string]configurationtypes.URL `json:"urls" yaml:"urls"` - LogLevel string `json:"log_level" yaml:"log_level"` + DefaultCache *configurationtypes.DefaultCache `json:"default_cache" yaml:"default_cache"` + API configurationtypes.API `json:"api" yaml:"api"` + CacheKeys configurationtypes.CacheKeys `json:"cache_keys" yaml:"cache_keys"` + URLs map[string]configurationtypes.URL `json:"urls" yaml:"urls"` + LogLevel string `json:"log_level" yaml:"log_level"` Logger *zap.Logger Ykeys map[string]configurationtypes.SurrogateKeys `json:"ykeys" yaml:"ykeys"` SurrogateKeys map[string]configurationtypes.SurrogateKeys `json:"surrogate_keys" yaml:"surrogate_keys"` @@ -58,7 +58,7 @@ func (c *BaseConfiguration) GetSurrogateKeys() map[string]configurationtypes.Sur } // GetCacheKeys get the cache keys rules to override -func (c *BaseConfiguration) GetCacheKeys() map[configurationtypes.RegValue]configurationtypes.Key { +func (c *BaseConfiguration) GetCacheKeys() configurationtypes.CacheKeys { return c.CacheKeys } diff --git a/plugins/traefik/vendor/github.com/darkweak/souin/pkg/rfc/age.go b/plugins/traefik/vendor/github.com/darkweak/souin/pkg/rfc/age.go index 9dc315f0e..6f95caa36 100644 --- a/plugins/traefik/vendor/github.com/darkweak/souin/pkg/rfc/age.go +++ b/plugins/traefik/vendor/github.com/darkweak/souin/pkg/rfc/age.go @@ -18,7 +18,13 @@ func validateMaxAgeCachedResponse(res *http.Response, maxAge int, addTime int) * } func ValidateMaxAgeCachedResponse(co *cacheobject.RequestCacheDirectives, res *http.Response) *http.Response { - return validateMaxAgeCachedResponse(res, int(co.MaxAge), 0) + responseCc, _ := cacheobject.ParseResponseCacheControl(res.Header.Get("Cache-Control")) + ma := co.MaxAge + if responseCc.SMaxAge > -1 { + ma = responseCc.SMaxAge + } + + return validateMaxAgeCachedResponse(res, int(ma), 0) } func ValidateMaxAgeCachedStaleResponse(co *cacheobject.RequestCacheDirectives, res *http.Response, addTime int) *http.Response { diff --git a/plugins/traefik/vendor/github.com/darkweak/souin/pkg/rfc/vary.go b/plugins/traefik/vendor/github.com/darkweak/souin/pkg/rfc/vary.go index 641b66b60..a72af7f7a 100644 --- a/plugins/traefik/vendor/github.com/darkweak/souin/pkg/rfc/vary.go +++ b/plugins/traefik/vendor/github.com/darkweak/souin/pkg/rfc/vary.go @@ -15,7 +15,7 @@ func GetVariedCacheKey(rq *http.Request, headers []string) string { return "" } for i, v := range headers { - h := strings.ToLower(strings.TrimSpace(rq.Header.Get(v))) + h := strings.TrimSpace(rq.Header.Get(v)) if strings.Contains(h, ";") || strings.Contains(h, ":") { h = url.QueryEscape(h) } diff --git a/plugins/traefik/vendor/github.com/darkweak/souin/pkg/storage/cacheProvider.go b/plugins/traefik/vendor/github.com/darkweak/souin/pkg/storage/cacheProvider.go index 6afa7a762..b11a0b44c 100644 --- a/plugins/traefik/vendor/github.com/darkweak/souin/pkg/storage/cacheProvider.go +++ b/plugins/traefik/vendor/github.com/darkweak/souin/pkg/storage/cacheProvider.go @@ -6,8 +6,8 @@ import ( "strings" "time" + "github.com/akyoto/cache" t "github.com/darkweak/souin/configurationtypes" - "github.com/patrickmn/go-cache" ) // Cache provider type @@ -18,17 +18,17 @@ type Cache struct { // CacheConnectionFactory function create new Cache instance func CacheConnectionFactory(c t.AbstractConfigurationInterface) (Storer, error) { - provider := cache.New(1*time.Second, 1*time.Second) + provider := cache.New(1 * time.Second) return &Cache{Cache: provider, stale: c.GetDefaultCache().GetStale()}, nil } // ListKeys method returns the list of existing keys func (provider *Cache) ListKeys() []string { - items := provider.Items() - keys := make([]string, 0, len(items)) - for k := range items { - keys = append(keys, k) - } + var keys []string + provider.Cache.Range(func(key, _ interface{}) bool { + keys = append(keys, key.(string)) + return true + }) return keys } @@ -47,20 +47,23 @@ func (provider *Cache) Get(key string) []byte { // Prefix method returns the populated response if exists, empty response then func (provider *Cache) Prefix(key string, req *http.Request) []byte { var result []byte - - for k, v := range provider.Items() { + provider.Cache.Range(func(k, v interface{}) bool { if k == key { - return v.Object.([]byte) + result = v.([]byte) + return false } - if !strings.HasPrefix(k, key) { - continue + if !strings.HasPrefix(k.(string), key) { + return true } - if varyVoter(key, req, k) { - result = v.Object.([]byte) + if varyVoter(key, req, k.(string)) { + result = v.([]byte) + return false } - } + + return true + }) return result } @@ -90,11 +93,12 @@ func (provider *Cache) DeleteMany(key string) { return } - for k := range provider.Items() { - if re.MatchString(k) { - provider.Delete(k) + provider.Cache.Range(func(k, _ interface{}) bool { + if re.MatchString(k.(string)) { + provider.Delete(k.(string)) } - } + return true + }) } // Init method will @@ -104,7 +108,7 @@ func (provider *Cache) Init() error { // Reset method will reset or close provider func (provider *Cache) Reset() error { - provider.Cache.Flush() + provider.DeleteMany("*") return nil } diff --git a/plugins/traefik/vendor/github.com/darkweak/souin/plugins/souin/configuration/configuration.go b/plugins/traefik/vendor/github.com/darkweak/souin/plugins/souin/configuration/configuration.go index 0aacd3028..cb78e7c6a 100644 --- a/plugins/traefik/vendor/github.com/darkweak/souin/plugins/souin/configuration/configuration.go +++ b/plugins/traefik/vendor/github.com/darkweak/souin/plugins/souin/configuration/configuration.go @@ -9,15 +9,15 @@ import ( "gopkg.in/yaml.v3" ) -//Configuration holder +// Configuration holder type Configuration struct { - DefaultCache *configurationtypes.DefaultCache `yaml:"default_cache"` - CacheKeys map[configurationtypes.RegValue]configurationtypes.Key `yaml:"cache_keys"` - API configurationtypes.API `yaml:"api"` - ReverseProxyURL string `yaml:"reverse_proxy_url"` - SSLProviders []string `yaml:"ssl_providers"` - URLs map[string]configurationtypes.URL `yaml:"urls"` - LogLevel string `yaml:"log_level"` + DefaultCache *configurationtypes.DefaultCache `yaml:"default_cache"` + CacheKeys configurationtypes.CacheKeys `yaml:"cache_keys"` + API configurationtypes.API `yaml:"api"` + ReverseProxyURL string `yaml:"reverse_proxy_url"` + SSLProviders []string `yaml:"ssl_providers"` + URLs map[string]configurationtypes.URL `yaml:"urls"` + LogLevel string `yaml:"log_level"` logger *zap.Logger Ykeys map[string]configurationtypes.SurrogateKeys `yaml:"ykeys"` SurrogateKeys map[string]configurationtypes.SurrogateKeys `yaml:"surrogate_keys"` @@ -90,7 +90,7 @@ func (c *Configuration) GetSurrogateKeys() map[string]configurationtypes.Surroga } // GetCacheKeys get the cache keys rules to override -func (c *Configuration) GetCacheKeys() map[configurationtypes.RegValue]configurationtypes.Key { +func (c *Configuration) GetCacheKeys() configurationtypes.CacheKeys { return c.CacheKeys } diff --git a/plugins/traefik/vendor/github.com/darkweak/souin/plugins/souin/configuration/configuration.yml b/plugins/traefik/vendor/github.com/darkweak/souin/plugins/souin/configuration/configuration.yml index ed7671a4b..1376a611c 100644 --- a/plugins/traefik/vendor/github.com/darkweak/souin/plugins/souin/configuration/configuration.yml +++ b/plugins/traefik/vendor/github.com/darkweak/souin/plugins/souin/configuration/configuration.yml @@ -4,5 +4,10 @@ default_cache: regex: exclude: /excluded ttl: 5s +cache_keys: + .+: + disable_body: true + disable_url: false + disable_query: true log_level: debug reverse_proxy_url: 'http://traefik' diff --git a/plugins/traefik/vendor/modules.txt b/plugins/traefik/vendor/modules.txt index aa42900a4..260a64b57 100644 --- a/plugins/traefik/vendor/modules.txt +++ b/plugins/traefik/vendor/modules.txt @@ -3,6 +3,9 @@ github.com/RoaringBitmap/roaring github.com/RoaringBitmap/roaring/internal github.com/RoaringBitmap/roaring/roaring64 +# github.com/akyoto/cache v1.0.6 +## explicit; go 1.13 +github.com/akyoto/cache # github.com/armon/go-metrics v0.4.1 ## explicit; go 1.12 github.com/armon/go-metrics @@ -65,7 +68,7 @@ github.com/coreos/go-systemd/v22/journal # github.com/darkweak/go-esi v0.0.5 ## explicit; go 1.18 github.com/darkweak/go-esi/esi -# github.com/darkweak/souin v1.6.35 => ../.. +# github.com/darkweak/souin v1.6.36 => ../.. ## explicit; go 1.16 github.com/darkweak/souin/cache/providers github.com/darkweak/souin/cache/types diff --git a/plugins/tyk/go.mod b/plugins/tyk/go.mod index fad53177f..591f94ec5 100644 --- a/plugins/tyk/go.mod +++ b/plugins/tyk/go.mod @@ -5,7 +5,7 @@ go 1.16 require ( github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect github.com/TykTechnologies/tyk v1.9.2-0.20220905191535-f610431668e4 - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 github.com/eclipse/paho.mqtt.golang v1.4.1 // indirect github.com/evanphx/json-patch/v5 v5.5.0 // indirect github.com/gobwas/ws v1.1.0 // indirect @@ -32,4 +32,4 @@ require ( gorm.io/gorm v1.23.9 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../.. diff --git a/plugins/tyk/override/context/key.go b/plugins/tyk/override/context/key.go index d2253b6f6..718e18cdb 100644 --- a/plugins/tyk/override/context/key.go +++ b/plugins/tyk/override/context/key.go @@ -22,7 +22,7 @@ type keyContext struct { disable_query bool displayable bool headers []string - overrides map[*regexp.Regexp]keyContext + overrides []map[*regexp.Regexp]keyContext } func (g *keyContext) SetupContext(c configurationtypes.AbstractConfigurationInterface) { @@ -30,19 +30,22 @@ func (g *keyContext) SetupContext(c configurationtypes.AbstractConfigurationInte g.disable_body = k.DisableBody g.disable_host = k.DisableHost g.disable_method = k.DisableMethod + g.disable_query = k.DisableQuery g.displayable = !k.Hide g.headers = k.Headers - g.overrides = make(map[*regexp.Regexp]keyContext) - - for r, v := range c.GetCacheKeys() { - g.overrides[r.Regexp] = keyContext{ - disable_body: v.DisableBody, - disable_host: v.DisableHost, - disable_method: v.DisableMethod, - disable_query: v.DisableQuery, - displayable: v.Hide, - headers: v.Headers, + g.overrides = make([]map[*regexp.Regexp]keyContext, 0) + + for _, cacheKey := range c.GetCacheKeys() { + for r, v := range cacheKey { + g.overrides = append(g.overrides, map[*regexp.Regexp]keyContext{r.Regexp: { + disable_body: v.DisableBody, + disable_host: v.DisableHost, + disable_method: v.DisableMethod, + disable_query: v.DisableQuery, + displayable: !v.Hide, + headers: v.Headers, + }}) } } } @@ -55,6 +58,7 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { if req.TLS != nil { scheme = "https-" } + query := "" body := "" host := "" method := "" @@ -62,7 +66,7 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { displayable := g.displayable if !g.disable_query && len(req.URL.RawQuery) > 0 { - key += "?" + req.URL.RawQuery + query += "?" + req.URL.RawQuery } if !g.disable_body { @@ -82,27 +86,39 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { headerValues += "-" + req.Header.Get(hn) } - for k, v := range g.overrides { - if k.MatchString(req.RequestURI) { - displayable = v.displayable - host = "" - method = "" - if !v.disable_body { - body = req.Context().Value(HashBody).(string) - } - if !v.disable_method { - method = req.Method + "-" - } - if !v.disable_host { - host = req.Host + "-" - } - if len(v.headers) > 0 { - headerValues = "" - for _, hn := range v.headers { - headers = v.headers - headerValues += "-" + req.Header.Get(hn) + hasOverride := false + for _, current := range g.overrides { + for k, v := range current { + if k.MatchString(req.RequestURI) { + displayable = v.displayable + host = "" + method = "" + query = "" + if !v.disable_query && len(req.URL.RawQuery) > 0 { + query = "?" + req.URL.RawQuery + } + if !v.disable_body { + body = req.Context().Value(HashBody).(string) } + if !v.disable_method { + method = req.Method + "-" + } + if !v.disable_host { + host = req.Host + "-" + } + if len(v.headers) > 0 { + headerValues = "" + for _, hn := range v.headers { + headers = v.headers + headerValues += "-" + req.Header.Get(hn) + } + } + hasOverride = true + break } + } + + if hasOverride { break } } @@ -113,7 +129,7 @@ func (g *keyContext) SetContext(req *http.Request) *http.Request { context.WithValue( req.Context(), Key, - method+scheme+host+key+body+headerValues, + method+scheme+host+key+query+body+headerValues, ), IgnoredHeaders, headers, diff --git a/plugins/webgo/go.mod b/plugins/webgo/go.mod index abe6f72e7..b08da9ec5 100644 --- a/plugins/webgo/go.mod +++ b/plugins/webgo/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/bnkamalesh/webgo/v6 v6.7.0 - github.com/darkweak/souin v1.6.35 + github.com/darkweak/souin v1.6.36 ) require ( @@ -83,4 +83,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/darkweak/souin v1.6.35 => ../.. +replace github.com/darkweak/souin v1.6.36 => ../..