Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(configuration): extends with allowed_addional_status_code #577

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ default_cache:
- GET
- POST
- HEAD
allowed_addional_status_code: # Allowed additional HTTP status code to cache.
- 202
- 400
cache_name: Souin # Override the cache name to use in the Cache-Status header
distributed: true # Use Olric or Etcd distributed storage
key:
Expand Down Expand Up @@ -196,6 +199,7 @@ surrogate_keys:
| `cdn.service_id` | The service id if required, depending the provider | `123456_id` |
| `cdn.zone_id` | The zone id if required, depending the provider | `anywhere_zone` |
| `default_cache.allowed_http_verbs` | The HTTP verbs to support cache | `- GET`<br/><br/>`- POST`<br/><br/>`(default: GET, HEAD)` |
| `default_cache.allowed_addional_status_code` | The additional HTTP status code to support cache | `- 200`<br/><br/>`- 404` |
| `default_cache.badger` | Configure the Badger cache storage | |
| `default_cache.badger.path` | Configure Badger with a file | `/anywhere/badger_configuration.json` |
| `default_cache.badger.configuration` | Configure Badger directly in the Caddyfile or your JSON caddy configuration | [See the Badger configuration for the options](https://dgraph.io/docs/badger/get-started/) |
Expand Down Expand Up @@ -425,6 +429,7 @@ There is the fully configuration below
}
cache {
allowed_http_verbs GET POST PATCH
allowed_addional_status_code 202
api {
basepath /some-basepath
prometheus {
Expand Down Expand Up @@ -882,6 +887,9 @@ http:
- GET
- POST
- HEAD
allowed_addional_status_code:
- 202
- 400
cdn:
api_key: XXXX
dynamic: true
Expand Down Expand Up @@ -979,6 +987,9 @@ http:
- GET
- HEAD
- POST
allowed_addional_status_code:
- 202
- 400
default_cache_control: no-store
log_level: debug
urls:
Expand Down
3 changes: 3 additions & 0 deletions configuration/configuration.sample.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ default_cache: # Required part
- GET
- POST
- HEAD
allowed_addional_status_code: # Allowed additional HTTP status code to cache.
- 202
- 400
cache_name: Souin # Override the Cache-Status name
distributed: true # Use Olric distributed storage
headers: # Default headers concatenated in stored keys
Expand Down
55 changes: 31 additions & 24 deletions configurationtypes/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,37 +230,43 @@ type Key struct {

// DefaultCache configuration
type DefaultCache struct {
AllowedHTTPVerbs []string `json:"allowed_http_verbs" yaml:"allowed_http_verbs"`
Badger CacheProvider `json:"badger" yaml:"badger"`
CDN CDN `json:"cdn" yaml:"cdn"`
CacheName string `json:"cache_name" yaml:"cache_name"`
Distributed bool `json:"distributed" yaml:"distributed"`
Headers []string `json:"headers" yaml:"headers"`
Key Key `json:"key" yaml:"key"`
Etcd CacheProvider `json:"etcd" yaml:"etcd"`
Mode string `json:"mode" yaml:"mode"`
Nats CacheProvider `json:"nats" yaml:"nats"`
Nuts CacheProvider `json:"nuts" yaml:"nuts"`
Olric CacheProvider `json:"olric" yaml:"olric"`
Otter CacheProvider `json:"otter" yaml:"otter"`
Redis CacheProvider `json:"redis" yaml:"redis"`
Port Port `json:"port" yaml:"port"`
Regex Regex `json:"regex" yaml:"regex"`
SimpleFS CacheProvider `json:"simplefs" yaml:"simplefs"`
Stale Duration `json:"stale" yaml:"stale"`
Storers []string `json:"storers" yaml:"storers"`
Timeout Timeout `json:"timeout" yaml:"timeout"`
TTL Duration `json:"ttl" yaml:"ttl"`
DefaultCacheControl string `json:"default_cache_control" yaml:"default_cache_control"`
MaxBodyBytes uint64 `json:"max_cacheable_body_bytes" yaml:"max_cacheable_body_bytes"`
DisableCoalescing bool `json:"disable_coalescing" yaml:"disable_coalescing"`
AllowedHTTPVerbs []string `json:"allowed_http_verbs" yaml:"allowed_http_verbs"`
AllowedAdditionalStatusCodes []int `json:"allowed_additional_status_codes" yaml:"allowed_additional_status_codes"`
Badger CacheProvider `json:"badger" yaml:"badger"`
CDN CDN `json:"cdn" yaml:"cdn"`
CacheName string `json:"cache_name" yaml:"cache_name"`
Distributed bool `json:"distributed" yaml:"distributed"`
Headers []string `json:"headers" yaml:"headers"`
Key Key `json:"key" yaml:"key"`
Etcd CacheProvider `json:"etcd" yaml:"etcd"`
Mode string `json:"mode" yaml:"mode"`
Nats CacheProvider `json:"nats" yaml:"nats"`
Nuts CacheProvider `json:"nuts" yaml:"nuts"`
Olric CacheProvider `json:"olric" yaml:"olric"`
Otter CacheProvider `json:"otter" yaml:"otter"`
Redis CacheProvider `json:"redis" yaml:"redis"`
Port Port `json:"port" yaml:"port"`
Regex Regex `json:"regex" yaml:"regex"`
SimpleFS CacheProvider `json:"simplefs" yaml:"simplefs"`
Stale Duration `json:"stale" yaml:"stale"`
Storers []string `json:"storers" yaml:"storers"`
Timeout Timeout `json:"timeout" yaml:"timeout"`
TTL Duration `json:"ttl" yaml:"ttl"`
DefaultCacheControl string `json:"default_cache_control" yaml:"default_cache_control"`
MaxBodyBytes uint64 `json:"max_cacheable_body_bytes" yaml:"max_cacheable_body_bytes"`
DisableCoalescing bool `json:"disable_coalescing" yaml:"disable_coalescing"`
}

// GetAllowedHTTPVerbs returns the allowed verbs to cache
func (d *DefaultCache) GetAllowedHTTPVerbs() []string {
return d.AllowedHTTPVerbs
}

// GetAllowedAdditionalStatusCodes returns the allowed verbs to cache
func (d *DefaultCache) GetAllowedAdditionalStatusCodes() []int {
return d.AllowedAdditionalStatusCodes
}

// GetBadger returns the Badger configuration
func (d *DefaultCache) GetBadger() CacheProvider {
return d.Badger
Expand Down Expand Up @@ -374,6 +380,7 @@ func (d *DefaultCache) IsCoalescingDisable() bool {
// DefaultCacheInterface interface
type DefaultCacheInterface interface {
GetAllowedHTTPVerbs() []string
GetAllowedAdditionalStatusCodes() []int
GetBadger() CacheProvider
GetCacheName() string
GetCDN() CDN
Expand Down
4 changes: 4 additions & 0 deletions docs/website/content/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ The default_cache prefix configure the default cache behavior. (e.g. `default_ca
The allowed_http_verbs prefix configure the HTTP verbs allowed to get cached. (e.g. `default_cache.allowed_http_verbs`).
default: `[GET, HEAD]`

#### Allowed additional status code
The allowed_addional_status_code prefix configure the additional HTTP status codes allowed to get cached. (e.g. `default_cache.allowed_addional_status_code`).
default: `[]`

#### Badger
The badger prefix configure the badger storage. (e.g. `default_cache.badger`).

Expand Down
16 changes: 13 additions & 3 deletions pkg/middleware/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,16 @@ func canBypassAuthorizationRestriction(headers http.Header, bypassed []string) b
return strings.Contains(strings.ToLower(headers.Get("Vary")), "authorization")
}

func (s *SouinBaseHandler) hasAllowedAdditionalStatusCodesToCache(code int) bool {
for _, sc := range s.Configuration.GetDefaultCache().GetAllowedAdditionalStatusCodes() {
if sc == code {
return true
}
}

return false
}

func (s *SouinBaseHandler) Store(
customWriter *CustomWriter,
rq *http.Request,
Expand All @@ -212,7 +222,7 @@ func (s *SouinBaseHandler) Store(
uri string,
) error {
statusCode := customWriter.GetStatusCode()
if !isCacheableCode(statusCode) {
if !isCacheableCode(statusCode) && !s.hasAllowedAdditionalStatusCodesToCache(statusCode) {
customWriter.Header().Set("Cache-Status", fmt.Sprintf("%s; fwd=uri-miss; key=%s; detail=UNCACHEABLE-STATUS-CODE", rq.Context().Value(context.CacheName), rfc.GetCacheKeyFromCtx(rq.Context())))

switch statusCode {
Expand Down Expand Up @@ -323,7 +333,7 @@ func (s *SouinBaseHandler) Store(
}
res.Header.Set(rfc.StoredLengthHeader, res.Header.Get("Content-Length"))
response, err := httputil.DumpResponse(&res, true)
if err == nil && (bLen > 0 || canStatusCodeEmptyContent(statusCode)) {
if err == nil && (bLen > 0 || canStatusCodeEmptyContent(statusCode) || s.hasAllowedAdditionalStatusCodesToCache(statusCode)) {
variedHeaders, isVaryStar := rfc.VariedHeaderAllCommaSepValues(res.Header)
if isVaryStar {
// "Implies that the response is uncacheable"
Expand Down Expand Up @@ -442,7 +452,7 @@ func (s *SouinBaseHandler) Upstream(
s.SurrogateKeyStorer.Invalidate(rq.Method, customWriter.Header())

statusCode := customWriter.GetStatusCode()
if !isCacheableCode(statusCode) {
if !isCacheableCode(statusCode) && !s.hasAllowedAdditionalStatusCodesToCache(statusCode) {
customWriter.Header().Set("Cache-Status", fmt.Sprintf("%s; fwd=uri-miss; key=%s; detail=UNCACHEABLE-STATUS-CODE", rq.Context().Value(context.CacheName), rfc.GetCacheKeyFromCtx(rq.Context())))

switch statusCode {
Expand Down
4 changes: 3 additions & 1 deletion plugins/beego/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ require (
github.com/darkweak/storages/olric v0.0.8 // indirect
github.com/darkweak/storages/otter v0.0.8 // indirect
github.com/darkweak/storages/redis v0.0.8 // indirect
github.com/darkweak/storages/simplefs v0.0.11 // indirect
github.com/dgraph-io/badger v1.6.2 // indirect
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
github.com/dgraph-io/badger/v3 v3.2103.5 // indirect
Expand Down Expand Up @@ -94,6 +95,7 @@ require (
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgtype v1.14.0 // indirect
github.com/jackc/pgx/v4 v4.18.3 // indirect
github.com/jellydator/ttlcache/v3 v3.3.0 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/libdns/libdns v0.2.2 // indirect
Expand Down Expand Up @@ -168,7 +170,7 @@ require (
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
Expand Down
8 changes: 6 additions & 2 deletions plugins/beego/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ github.com/darkweak/storages/otter v0.0.8 h1:Tsv4NiLAiZyvovs4oCWT+WQUYe5YvbFvEx2
github.com/darkweak/storages/otter v0.0.8/go.mod h1:BBYxyWClX3PFdbvns6W95kLNNihq1FxljBYGIzP4snI=
github.com/darkweak/storages/redis v0.0.8 h1:0CHLkImyaI/sYs+IOurYLAxFkrmz5dFblhfpF7oGhQc=
github.com/darkweak/storages/redis v0.0.8/go.mod h1:pypJ5T3hweQWfHzFUjmZWeb1KaNK3ikNg1+rn0G+rD0=
github.com/darkweak/storages/simplefs v0.0.11 h1:BagJxTJVtWCnCsQi4kMuJdHGN8LHzARAEEiQ1WJYJl4=
github.com/darkweak/storages/simplefs v0.0.11/go.mod h1:FegezzdPj5m3ExDea64WxcDxPz7dFdu8G5WoIaYfbLM=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -384,6 +386,8 @@ github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc=
github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
Expand Down Expand Up @@ -770,8 +774,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down
1 change: 1 addition & 0 deletions plugins/caddy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ What does these directives mean?
| Key | Description | Value example |
|:------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------|
| `allowed_http_verbs` | The HTTP verbs allowed to be cached | `GET POST PATCH`<br/><br/>`(default: GET HEAD)` |
| `allowed_addional_status_code` | The additional HTTP status codes allowed to be cached | `202 400` |
darkweak marked this conversation as resolved.
Show resolved Hide resolved
| `api` | The cache-handler API cache management | |
| `api.basepath` | BasePath for all APIs to avoid conflicts | `/your-non-conflict-route`<br/><br/>`(default: /souin-api)` |
| `api.prometheus` | Enable the Prometheus metrics | |
Expand Down
18 changes: 18 additions & 0 deletions plugins/caddy/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
type DefaultCache struct {
// Allowed HTTP verbs to be cached by the system.
AllowedHTTPVerbs []string `json:"allowed_http_verbs"`
// Allowed additional status code to be cached by the system.
AllowedAdditionalStatusCodes []int `json:"allowed_additional_status_codes"`
// Badger provider configuration.
Badger configurationtypes.CacheProvider `json:"badger"`
// The cache name to use in the Cache-Status response header.
Expand Down Expand Up @@ -65,6 +67,11 @@ func (d *DefaultCache) GetAllowedHTTPVerbs() []string {
return d.AllowedHTTPVerbs
}

// GetAllowedAdditionalStatusCodes returns the allowed verbs to cache
func (d *DefaultCache) GetAllowedAdditionalStatusCodes() []int {
return d.AllowedAdditionalStatusCodes
}

// GetBadger returns the Badger configuration
func (d *DefaultCache) GetBadger() configurationtypes.CacheProvider {
return d.Badger
Expand Down Expand Up @@ -364,6 +371,17 @@ func parseConfiguration(cfg *Configuration, h *caddyfile.Dispenser, isGlobal boo
allowed := cfg.DefaultCache.AllowedHTTPVerbs
allowed = append(allowed, h.RemainingArgs()...)
cfg.DefaultCache.AllowedHTTPVerbs = allowed
case "allowed_additional_status_codes":
allowed := cfg.DefaultCache.AllowedAdditionalStatusCodes
additional := h.RemainingArgs()
codes := make([]int, 0)
for _, code := range additional {
if c, err := strconv.Atoi(code); err == nil {
codes = append(codes, c)
}
}
allowed = append(allowed, codes...)
cfg.DefaultCache.AllowedAdditionalStatusCodes = allowed
case "api":
if !isGlobal {
return h.Err("'api' block must be global")
Expand Down
Loading
Loading