From bb573e60a6e47ede91b0c1645084ec8399e65f56 Mon Sep 17 00:00:00 2001 From: darkweak Date: Wed, 10 Jul 2024 23:53:30 +0200 Subject: [PATCH] feat(documentation): prepare release with external storages --- README.md | 98 ++----- docs/website/assets/docs/scss/style.scss | 26 +- docs/website/content/docs/configuration.md | 8 + docs/website/content/docs/introduction.md | 11 + .../website/content/docs/middlewares/caddy.md | 27 +- docs/website/content/docs/storages/add-own.md | 244 ++++++++++++++++++ docs/website/content/docs/storages/badger.md | 21 ++ .../content/docs/storages/embedded-olric.md | 21 ++ docs/website/content/docs/storages/etcd.md | 21 ++ docs/website/content/docs/storages/nuts.md | 21 ++ docs/website/content/docs/storages/olric.md | 21 ++ docs/website/content/docs/storages/otter.md | 21 ++ docs/website/content/docs/storages/redis.md | 21 ++ docs/website/hugo.toml | 5 + plugins/caddy/README.md | 5 + plugins/souin/storages/storages.go | 2 +- 16 files changed, 494 insertions(+), 79 deletions(-) create mode 100644 docs/website/content/docs/storages/add-own.md diff --git a/README.md b/README.md index 9f1e44c06..e53238e52 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,15 @@ 2.1.1. [Souin as plugin](#souin-as-plugin) 2.1.2. [Souin out-of-the-box](#souin-out-of-the-box) 2.2. [Optional configuration](#optional-configuration) -3. [APIs](#apis) - 3.1. [Prometheus API](#prometheus-api) - 3.2. [Souin API](#souin-api) - 3.3. [Security API](#security-api) -4. [Diagrams](#diagrams) - 4.1. [Sequence diagram](#sequence-diagram) -5. [Cache systems](#cache-systems) -6. [GraphQL](#graphql) -7. [Examples](#examples) - 7.1. [Træfik container](#træfik-container) +3. [Storages](#storages) +4. [APIs](#apis) + 4.1. [Prometheus API](#prometheus-api) + 4.2. [Souin API](#souin-api) + 4.3. [Security API](#security-api) +5. [Diagrams](#diagrams) + 5.1. [Sequence diagram](#sequence-diagram) +6. [Cache systems](#cache-systems) +7. [GraphQL](#graphql) 8. [Plugins](#plugins) 8.1. [Beego filter](#beego-filter) 8.2. [Caddy module](#caddy-module) @@ -35,8 +34,6 @@ 8.15. [Træfik plugin](#træfik-plugin) 8.16. [Tyk plugin](#tyk-plugin) 8.17. [Webgo middleware](#webgo-middleware) - 8.18. [Prestashop plugin](#prestashop-plugin) - 8.19. [Wordpress plugin](#wordpress-plugin) 9. [Credits](#credits) # Souin HTTP cache @@ -46,9 +43,14 @@ Souin is a new HTTP cache system suitable for every reverse-proxy. It can be eit Since it's written in go, it can be deployed on any server and thanks to the docker integration, it will be easy to install on top of a Swarm, or a kubernetes instance. It's RFC compatible, supporting Vary, request coalescing, stale cache-control and other specifications related to the [RFC-7234](https://tools.ietf.org/html/rfc7234). It supports the newly written RFCs (currently in draft) [http-cache-groups](https://datatracker.ietf.org/doc/draft-nottingham-http-cache-groups/) and [http-invalidation](https://datatracker.ietf.org/doc/draft-nottingham-http-invalidation/). -It also supports the [Cache-Status HTTP response header](https://www.rfc-editor.org/rfc/rfc9211) and the YKey group such as Varnish. +It also supports the [Cache-Status HTTP response header](https://www.rfc-editor.org/rfc/rfc9211), the YKey group such as Varnish, the [Targeted HTTP Cache Control RFC](https://www.rfc-editor.org/rfc/rfc9213), . It supports the ESI tags, thanks to the [go-esi package](https://github.com/darkweak/go-esi). +> [!WARNING] +> Since `v1.7.0` Souin implements only one storage. If you need a specific storage you have to take it from [the storages repository](https://github.com/darkweak/storages) and add it either in your code, during the build otherwise. +(e.g. with otter using caddy) You have to build your caddy module with the desired storage `xcaddy build --with github.com/darkweak/souin/plugins/caddy --with github.com/darkweak/storages/otter/caddy` and configure otter in your Caddyfile/JSON configuration file. +See the [storages section](#storages) or the [documentation website about the storages](https://docs.souin.io/docs/storages) + ## Configuration The configuration file is store at `/anywhere/configuration.yml`. You can supply your own as long as you use one of the minimal configurations below. @@ -93,6 +95,7 @@ cache_keys: headers: # Add headers to the key - Authorization # Add the header value in the key - Content-Type # Add the header value in the key + template: "{http.request.method}-{http.request.host}-{http.request.path}" # Use caddy placeholders to create the key (when this option is enabled, disable_* directives are skipped) cdn: # If Souin is set after a CDN fill these informations api_key: XXXX # Your provider API key if mandatory provider: fastly # The provider placed before Souin (e.g. fastly, cloudflare, akamai, varnish) @@ -211,7 +214,7 @@ surrogate_keys: | `default_cache.key.headers` | Add headers to the key matching the regexp | `- Authorization`

`- Content-Type`

`- X-Additional-Header` | | `default_cache.key.hide` | Prevent the key from being exposed in the `Cache-Status` HTTP response header | `true`

`(default: false)` | | `default_cache.key.template` | Use caddy placeholders to create the key (when this option is enabled, disable_* directives are skipped) | [Placeholders documentation](https://caddyserver.com/docs/caddyfile/concepts#placeholders) | -| `default_cache.max_cacheable_body_bytes` | Set the maximum size (in bytes) for a response body to be cached (unlimited if omited) | `1048576` (1MB) | +| `default_cache.max_cacheable_body_bytes` | Set the maximum size (in bytes) for a response body to be cached (unlimited if omited) | `1048576` (1MB) | | `default_cache.mode` | RFC respect tweaking | One of `bypass` `bypass_request` `bypass_response` `strict` (default `strict`) | | `default_cache.nuts` | Configure the Nuts cache storage | | | `default_cache.nuts.path` | Set the Nuts file path storage | `/anywhere/nuts/storage` | @@ -379,60 +382,6 @@ The cache invalidation is built for CRUD requests, if you're doing a GET HTTP re If you're doing a POST, PUT, PATCH or DELETE HTTP request, the related cache GET request, and the list endpoint will be dropped. It also supports invalidation via [Souin API](#souin-api) to invalidate the cache programmatically. -## Examples - -### Træfik container -[Træfik](https://traefik.io) is a modern reverse-proxy which helps you to manage full container architecture projects. - -```yaml -# your-traefik-instance/docker-compose.yml -version: '3.7' - -x-networks: &networks - networks: - - your_network - -services: - traefik: - image: traefik:v2.5.6 - command: --providers.docker - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - /anywhere/traefik.json:/acme.json - <<: *networks - - # your other services here... - -networks: - your_network: - external: true -``` - -```yaml -# your-souin-instance/docker-compose.yml -version: '3.7' - -x-networks: &networks - networks: - - your_network - -services: - souin: - image: darkweak/souin:latest - ports: - - 80:80 - - 443:443 - environment: - GOPATH: /app - volumes: - - /anywhere/traefik.json:/ssl/traefik.json - - /anywhere/configuration.yml:/configuration/configuration.yml - <<: *networks - -networks: - your_network: - external: true -``` ## Plugins @@ -1158,17 +1107,14 @@ func main(){ } ``` -### Prestashop plugin -A repository called [prestashop-souin](https://github.com/lucmichalski/prestashop-souin) has been started by [lucmichalski](https://github.com/lucmichalski). You can manage your Souin instance through the admin panel UI. - -### Wordpress plugin -A repository called [wordpress-souin](https://github.com/Darkweak/wordpress-souin) to be able to manage your Souin instance through the admin panel UI. - ## Credits Thanks to these users for contributing or helping this project in any way * [Oxodao](https://github.com/oxodao) * [Deuchnord](https://github.com/deuchnord) +* [Vincent Jordan](https://github.com/vejipe) +* [Mohammed Al Sahaf](https://github.com/mohammed90) +* [Hussam Almarzooq](https://github.com/hussam-almarzoq) * [Sata51](https://github.com/sata51) * [Pierre Diancourt](https://github.com/pierrediancourt) * [Burak Sezer](https://github.com/buraksezer) @@ -1192,3 +1138,7 @@ Thanks to these users for contributing or helping this project in any way * [JacquesDurand](https://github.com/jacquesdurand) * [Frederic Houle](https://github.com/frederichoule) * [Valery Piashchynski](https://github.com/rustatian) +* [Ivan Derda](https://github.com/HobMartin) +* [p0358](https://github.com/p0358) +* [Alberto Tablado](https://github.com/aluki) +* [Yong Zhang](https://github.com/yongzhang) diff --git a/docs/website/assets/docs/scss/style.scss b/docs/website/assets/docs/scss/style.scss index 90d3faf50..e3445e534 100644 --- a/docs/website/assets/docs/scss/style.scss +++ b/docs/website/assets/docs/scss/style.scss @@ -73,15 +73,31 @@ $code-block-padding-top: {{ if eq .Site.Params.docs.prism true -}}0{{ else }}1.2 @import "custom/plugins/mermaid/mermaid"; h1 { - padding-top: 1em; - padding-bottom: 1em; + margin-top: .5em; + font-weight: 900 !important; + margin-left: auto; + margin-right: auto; + padding: 0.1em 0.4em; + border-radius: 0.8em 0.3em; + background: transparent; + background-image: linear-gradient( + to right, + hsla(226, 66, 51, 0.3), + hsla(226, 66, 51, 0.1) + ); + -webkit-box-decoration-break: clone; + box-decoration-break: clone; } h2 { - padding-top: 0.5em; + padding-top: 1.5em; padding-bottom: 0.5em; } +h4 { + padding-top: 0.75em; +} + div.code-toolbar { border-radius: 1rem; & > pre { @@ -115,4 +131,8 @@ div.code-toolbar { display: flex; } } +} + +.alert > .w-100 { + overflow: hidden } \ No newline at end of file diff --git a/docs/website/content/docs/configuration.md b/docs/website/content/docs/configuration.md index 5c62b919f..c3facaf88 100644 --- a/docs/website/content/docs/configuration.md +++ b/docs/website/content/docs/configuration.md @@ -48,9 +48,13 @@ cache_keys: disable_host: true disable_method: true disable_query: true + disable_scheme: true + hash: true headers: - Authorization - Content-Type + hide: true + template: "{http.request.method}-{http.request.host}-{http.request.path}" ``` {{% /alert %}} @@ -77,6 +81,8 @@ default: `false` * **hide**: Prevent the key from being exposed in the `Cache-Status` HTTP response header. default: `false` +* **template**: Customize the key with the given template. It uses the caddy placeholders to create the key (when this option is enabled, disable_* directives are skipped). + ### CDN The cdn prefix configure the upfront CDN yuo have placed before Souin. It can handle ofr you the cache invalidation on your CDN, the optimization to have your pages cached directly on it. @@ -164,6 +170,8 @@ default: `false` * **hide**: Prevent the key from being exposed in the `Cache-Status` HTTP response header. default: `false` +* **template**: Customize the key with the given template. It uses the caddy placeholders to create the key (when this option is enabled, disable_* directives are skipped). + #### Max cacheable body bytes Limit to define if the body size is allowed to be cached. (e.g. `1048576` (1MB)). If a limit is set, your streamed/chunk responses won't be cached. diff --git a/docs/website/content/docs/introduction.md b/docs/website/content/docs/introduction.md index 776541441..71077cd50 100644 --- a/docs/website/content/docs/introduction.md +++ b/docs/website/content/docs/introduction.md @@ -19,6 +19,17 @@ Souin is a powerful HTTP cache system written in go and implements the following ## Multiple backend storages + +{{% alert context="warning" %}} +Since `v1.7.0` Souin implements only one storage, if you need a specific storage you have to take it from [the storages repository](https://github.com/darkweak/storages) and add it either in your code, during the build otherwise. +(e.g. with otter using caddy) You have to build your caddy module with the desired storage +```shell +xcaddy build --with github.com/darkweak/souin/plugins/caddy --with github.com/darkweak/storages/otter/caddy +``` +and configure otter in your Caddyfile/JSON configuration file. +See the [storages page]({{% relref "/docs/storages" %}}) to learn more about each supported storage. +{{% /alert %}} + ### Local in-memory or filesystem * [Badger]({{% relref "/docs/storages/badger" %}}) * [Nuts]({{% relref "/docs/storages/nuts" %}}) diff --git a/docs/website/content/docs/middlewares/caddy.md b/docs/website/content/docs/middlewares/caddy.md index f21fb5810..571779fd7 100644 --- a/docs/website/content/docs/middlewares/caddy.md +++ b/docs/website/content/docs/middlewares/caddy.md @@ -28,7 +28,6 @@ We need to tell caddy that it must use the HTTP cache with the `cache` global an ```caddyfile { debug - cache order before rewrite cache { ttl 1h } @@ -83,6 +82,32 @@ If we go on [https://localhost/souin-api/debug/](https://localhost/souin-api/deb ### Complex configuration #### Storages +{{% alert context="warning" %}} +Since `v1.7.0` Souin implements only an in-memory storage, if you need a specific storage you have to take it from [the storages repository](https://github.com/darkweak/storages) and add to your build command. +(e.g. with redis using caddy) You have to build your caddy module with the desired storage +```shell +xcaddy build --with github.com/darkweak/souin/plugins/caddy --with github.com/darkweak/storages/redis/caddy +``` +and configure redis in your Caddyfile/JSON configuration file. +See the [storages page]({{% relref "/docs/storages" %}}) to learn more about each supported storage. +{{% /alert %}} + +First you have to build Caddy with Souin and a storage using the following template. +``` +xcaddy build \ + --with github.com/darkweak/souin/plugins/caddy \ + --with github.com/darkweak/storages/{your_storage_name}/caddy +``` + +You can also use as many storages you want. +``` +xcaddy build \ + --with github.com/darkweak/souin/plugins/caddy \ + --with github.com/darkweak/storages/redis/caddy + --with github.com/darkweak/storages/nuts/caddy + --with github.com/darkweak/storages/otter/caddy +``` + We can define multiple storages to use to store the response from the upstream server and specify the order. Here, we define 3 storages `badger`, `nuts` and `redis` and `nuts` will be accessed first, `badger` the second and `redis` the third only if the previous doesn't return suitable data. diff --git a/docs/website/content/docs/storages/add-own.md b/docs/website/content/docs/storages/add-own.md new file mode 100644 index 000000000..e66b7c4c1 --- /dev/null +++ b/docs/website/content/docs/storages/add-own.md @@ -0,0 +1,244 @@ ++++ +weight = 408 +title = "Add your own storage" +icon = "home_storage" +description = "Badger is an in-memory storage system" +tags = ["Beginners"] ++++ + +## Context +The [storage repository](https://github.com/darkweak/storages) defines an interface called `Storer` in the [core/core.go file](https://github.com/darkweak/storages/blob/main/core/core.go) that should be implemented by your storage. +Your `struct` must implement it to be a valid storer and be registered in the storage pool. + +By convention we declare a `Factory` function that respects this signature: +```go +func(providerConfiguration core.CacheProvider, logger *zap.Logger, stale time.Duration) (core.Storer, error) +``` + +And the `Storer` interface is the following: +```go +type Storer interface { + MapKeys(prefix string) map[string]string + ListKeys() []string + Get(key string) []byte + Set(key string, value []byte, duration time.Duration) error + Delete(key string) + DeleteMany(key string) + Init() error + Name() string + Uuid() string + Reset() error + + // Multi level storer to handle fresh/stale at once + GetMultiLevel(key string, req *http.Request, validator *Revalidator) (fresh *http.Response, stale *http.Response) + SetMultiLevel(baseKey, variedKey string, value []byte, variedHeaders http.Header, etag string, duration time.Duration, realKey string) error +} +``` + +## Example +Let's define our simple in-memory storage +```go +// your_custom_storage.go +package your_package + +import ( + "sync" + "time" + + "github.com/darkweak/souin/pkg/storage/types" + "github.com/darkweak/storages/core" + "go.uber.org/zap" +) + +// custom storage provider type +type customStorage struct { + m *sync.Map + stale time.Duration + logger *zap.Logger +} + +// Factory function create new custom storage instance +func Factory(_ core.CacheProvider, logger *zap.Logger, stale time.Duration) (types.Storer, error) { + return &customStorage{m: &sync.Map{}, logger: logger, stale: stale}, nil +} +``` + +We have to implement the `Storer` interface now. +```go +// your_custom_storage.go +... + +// Name returns the storer name +func (provider *customStorage) Name() string { + return "YOUR_CUSTOM_STORAGE" +} + +// Uuid returns an unique identifier +func (provider *customStorage) Uuid() string { + return "THE_UUID" +} + +// MapKeys method returns a map with the key and value +func (provider *customStorage) MapKeys(prefix string) map[string]string { + now := time.Now() + keys := map[string]string{} + + provider.m.Range(func(key, value any) bool { + if strings.HasPrefix(key.(string), prefix) { + k, _ := strings.CutPrefix(key.(string), prefix) + if v, ok := value.(core.StorageMapper); ok { + for _, v := range v.Mapping { + if v.StaleTime.After(now) { + keys[v.RealKey] = string(provider.Get(v.RealKey)) + } + } + + return true + } + + keys[k] = string(value.([]byte)) + } + + return true + }) + + return keys +} + +// ListKeys method returns the list of existing keys +func (provider *customStorage) ListKeys() []string { + now := time.Now() + keys := []string{} + + provider.m.Range(func(key, value any) bool { + if strings.HasPrefix(key.(string), core.MappingKeyPrefix) { + mapping, err := core.DecodeMapping(value.([]byte)) + if err == nil { + for _, v := range mapping.Mapping { + if v.StaleTime.After(now) { + keys = append(keys, v.RealKey) + } else { + provider.m.Delete(v.RealKey) + } + } + } + } + + return true + }) + + return keys +} + +// Get method returns the populated response if exists, empty response then +func (provider *customStorage) Get(key string) []byte { + result, ok := provider.m.Load(key) + if !ok || result == nil { + return nil + } + + res, ok := result.([]byte) + if !ok { + return nil + } + + return res +} + +// GetMultiLevel tries to load the key and check if one of linked keys is a fresh/stale candidate. +func (provider *customStorage) GetMultiLevel(key string, req *http.Request, validator *core.Revalidator) (fresh *http.Response, stale *http.Response) { + result, found := provider.m.Load(core.MappingKeyPrefix + key) + if !found { + return + } + + fresh, stale, _ = core.MappingElection(provider, result.([]byte), req, validator, provider.logger) + + return +} + +// SetMultiLevel tries to store the key with the given value and update the mapping key to store metadata. +func (provider *customStorage) SetMultiLevel(baseKey, variedKey string, value []byte, variedHeaders http.Header, etag string, duration time.Duration, realKey string) error { + now := time.Now() + + var e error + compressed := new(bytes.Buffer) + if _, e = lz4.NewWriter(compressed).ReadFrom(bytes.NewReader(value)); e != nil { + provider.logger.Sugar().Errorf("Impossible to compress the key %s into Badger, %v", variedKey, e) + return e + } + + provider.m.Store(variedKey, compressed.Bytes()) + + mappingKey := core.MappingKeyPrefix + baseKey + item, ok := provider.m.Load(mappingKey) + var val []byte + if ok { + val = item.([]byte) + } + + val, e = core.MappingUpdater(variedKey, val, provider.logger, now, now.Add(duration), now.Add(duration+provider.stale), variedHeaders, etag, realKey) + if e != nil { + return e + } + + provider.logger.Sugar().Debugf("Store the new mapping for the key %s in customStorage", variedKey) + provider.m.Store(mappingKey, val) + return nil +} + +// Set method will store the response in Badger provider +func (provider *customStorage) Set(key string, value []byte, duration time.Duration) error { + provider.m.Store(key, value) + + return nil +} + +// Delete method will delete the response in Badger provider if exists corresponding to key param +func (provider *customStorage) Delete(key string) { + provider.m.Delete(key) +} + +// DeleteMany method will delete the responses in Badger provider if exists corresponding to the regex key param +func (provider *customStorage) DeleteMany(key string) { + re, e := regexp.Compile(key) + + if e != nil { + return + } + + provider.m.Range(func(key, _ any) bool { + if re.MatchString(key.(string)) { + provider.m.Delete(key) + } + + return true + }) +} + +// Init method will +func (provider *customStorage) Init() error { + return nil +} + +// Reset method will reset or close provider +func (provider *customStorage) Reset() error { + provider.m = &sync.Map{} + return nil +} +``` + +After that you'll be able to register your storage using +```go +// anywhere.go +... +logger, _ := zap.NewProduction() +customStorage, _ := your_package.Factory(core.CacheProvider{}, logger, time.Hour) +// It will register as `YOUR_CUSTOM_STORAGE-THE_UUID`. +core.RegisterStorage(customStorage) + +// In your code +if st := core.GetRegisteredStorer("YOUR_CUSTOM_STORAGE-THE_UUID"); st != nil { + customStorage = st.(types.Storer) +} +``` diff --git a/docs/website/content/docs/storages/badger.md b/docs/website/content/docs/storages/badger.md index e28c54192..4997e23a6 100644 --- a/docs/website/content/docs/storages/badger.md +++ b/docs/website/content/docs/storages/badger.md @@ -12,6 +12,27 @@ BadgerDB is an embeddable, persistent and fast key-value (KV) database written i ## Github repository [https://github.com/dgraph-io/badger](https://github.com/dgraph-io/badger) +## Use Badger +### With Caddy +You have to build your caddy instance including `Souin` and `Badger` using `xcaddy` ([refer to the build caddy section]({{% relref "/docs/middlewares/caddy#build-your-caddy-binary" %}})). +```shell +xcaddy build --with github.com/darkweak/souin/plugins/caddy --with github.com/darkweak/storages/badger/caddy +``` +You will be able to use badger in your Caddyfile or JSON configuration file. +```caddyfile +{ + cache { + ttl 1h + badger + } +} + +route { + cache + respond "Hello HTTP cache" +} +``` + ## Configuration You can find the configuration for Badger [here](https://github.com/dgraph-io/badger/blob/main/options.go#L44) or check the values table below. diff --git a/docs/website/content/docs/storages/embedded-olric.md b/docs/website/content/docs/storages/embedded-olric.md index 9e7ff3d74..9c570a1fb 100644 --- a/docs/website/content/docs/storages/embedded-olric.md +++ b/docs/website/content/docs/storages/embedded-olric.md @@ -18,6 +18,27 @@ Olric is highly scalable and available. Distributed applications can use it for ## Github repository [https://github.com/buraksezer/olric](https://github.com/buraksezer/olric) +## Use Embedded Olric +### With Caddy +You have to build your caddy instance including `Souin` and `Embedded Olric` using `xcaddy` ([refer to the build caddy section]({{% relref "/docs/middlewares/caddy#build-your-caddy-binary" %}})). +```shell +xcaddy build --with github.com/darkweak/souin/plugins/caddy --with github.com/darkweak/storages/olric/caddy +``` +You will be able to use olric in your Caddyfile or JSON configuration file. +```caddyfile +{ + cache { + ttl 1h + olric + } +} + +route { + cache + respond "Hello HTTP cache" +} +``` + ## Configuration You can find the configuration for the Embedded Olric [here](https://github.com/buraksezer/olric/blob/master/config/config.go#L167) or check the values table below. diff --git a/docs/website/content/docs/storages/etcd.md b/docs/website/content/docs/storages/etcd.md index 586ebeb8e..e11cfca81 100644 --- a/docs/website/content/docs/storages/etcd.md +++ b/docs/website/content/docs/storages/etcd.md @@ -18,6 +18,27 @@ etcd is written in Go and uses the Raft consensus algorithm to manage a highly-a ## Github repository [https://github.com/etcd-io/etcd](https://github.com/etcd-io/etcd) +## Use Etcd +### With Caddy +You have to build your caddy instance including `Souin` and `Etcd` using `xcaddy` ([refer to the build caddy section]({{% relref "/docs/middlewares/caddy#build-your-caddy-binary" %}})). +```shell +xcaddy build --with github.com/darkweak/souin/plugins/caddy --with github.com/darkweak/storages/etcd/caddy +``` +You will be able to use etcd in your Caddyfile or JSON configuration file. +```caddyfile +{ + cache { + ttl 1h + etcd + } +} + +route { + cache + respond "Hello HTTP cache" +} +``` + ## Configuration You can find the configuration for Etcd [here](https://github.com/etcd-io/etcd/blob/main/client/v3/config.go#L28) or check the values table below. diff --git a/docs/website/content/docs/storages/nuts.md b/docs/website/content/docs/storages/nuts.md index 4459f9d13..ce85dc407 100644 --- a/docs/website/content/docs/storages/nuts.md +++ b/docs/website/content/docs/storages/nuts.md @@ -14,6 +14,27 @@ It supports fully serializable transactions and many data structures such as lis ## Github repository [https://github.com/nutsdb/nutsdb](https://github.com/nutsdb/nutsdb) +## Use Nuts +### With Caddy +You have to build your caddy instance including `Souin` and `Nuts` using `xcaddy` ([refer to the build caddy section]({{% relref "/docs/middlewares/caddy#build-your-caddy-binary" %}})). +```shell +xcaddy build --with github.com/darkweak/souin/plugins/caddy --with github.com/darkweak/storages/nuts/caddy +``` +You will be able to use nuts in your Caddyfile or JSON configuration file. +```caddyfile +{ + cache { + ttl 1h + nuts + } +} + +route { + cache + respond "Hello HTTP cache" +} +``` + ## Configuration You can find the configuration for Nuts [here](https://github.com/nutsdb/nutsdb/blob/master/options.go#L55) or check the values table below. diff --git a/docs/website/content/docs/storages/olric.md b/docs/website/content/docs/storages/olric.md index b6475ecac..f6bb4a667 100644 --- a/docs/website/content/docs/storages/olric.md +++ b/docs/website/content/docs/storages/olric.md @@ -21,6 +21,27 @@ Olric is highly scalable and available. Distributed applications can use it for ## Github repository [https://github.com/buraksezer/olric](https://github.com/buraksezer/olric) +## Use Olric +### With Caddy +You have to build your caddy instance including `Souin` and `Olric` using `xcaddy` ([refer to the build caddy section]({{% relref "/docs/middlewares/caddy#build-your-caddy-binary" %}})). +```shell +xcaddy build --with github.com/darkweak/souin/plugins/caddy --with github.com/darkweak/storages/olric/caddy +``` +You will be able to use olric in your Caddyfile or JSON configuration file. +```caddyfile +{ + cache { + ttl 1h + olric + } +} + +route { + cache + respond "Hello HTTP cache" +} +``` + ## Configuration {{% alert context="warning" %}} You can't configure in Souin the Olric server instance. diff --git a/docs/website/content/docs/storages/otter.md b/docs/website/content/docs/storages/otter.md index d1e2e70c3..2aa46f5e8 100644 --- a/docs/website/content/docs/storages/otter.md +++ b/docs/website/content/docs/storages/otter.md @@ -12,6 +12,27 @@ Otter is a high performance lockless cache for Go. Many times faster than Ristre ## Github repository [https://github.com/maypok86/otter](https://github.com/maypok86/otter) +## Use Otter +### With Caddy +You have to build your caddy instance including `Souin` and `Otter` using `xcaddy` ([refer to the build caddy section]({{% relref "/docs/middlewares/caddy#build-your-caddy-binary" %}})). +```shell +xcaddy build --with github.com/darkweak/souin/plugins/caddy --with github.com/darkweak/storages/otter/caddy +``` +You will be able to use otter in your Caddyfile or JSON configuration file. +```caddyfile +{ + cache { + ttl 1h + otter + } +} + +route { + cache + respond "Hello HTTP cache" +} +``` + ## Configuration You can find the configuration for Otter with the values table below. By default the cache size is for 10_000 elements. diff --git a/docs/website/content/docs/storages/redis.md b/docs/website/content/docs/storages/redis.md index 796caec9b..4208ce892 100644 --- a/docs/website/content/docs/storages/redis.md +++ b/docs/website/content/docs/storages/redis.md @@ -16,6 +16,27 @@ Redis is often referred to as a data structures server. What this means is that ## Github repository [https://github.com/redis/rueidis](https://github.com/redis/rueidis) +## Use Redis +### With Caddy +You have to build your caddy instance including `Souin` and `Redis` using `xcaddy` ([refer to the build caddy section]({{% relref "/docs/middlewares/caddy#build-your-caddy-binary" %}})). +```shell +xcaddy build --with github.com/darkweak/souin/plugins/caddy --with github.com/darkweak/storages/redis/caddy +``` +You will be able to use redis in your Caddyfile or JSON configuration file. +```caddyfile +{ + cache { + ttl 1h + redis + } +} + +route { + cache + respond "Hello HTTP cache" +} +``` + ## Configuration You can find the configuration for Redis [here](https://github.com/redis/rueidis/blob/master/options.go#L31) or check the values table below. diff --git a/docs/website/hugo.toml b/docs/website/hugo.toml index 87cb936ba..20d026461 100644 --- a/docs/website/hugo.toml +++ b/docs/website/hugo.toml @@ -13,12 +13,17 @@ disable = false [params.footer] copyright = "2024" +[params.social] +github = "darkweak/souin" +twitter = "darkweak_dev" + [params.docs] intLinkTooltip = true darkMode = true sidebarIcons = true prism = true scrollSpy = true +title = "Souin's documentation" [markup.goldmark.renderer] unsafe = true diff --git a/plugins/caddy/README.md b/plugins/caddy/README.md index 1ec2117de..aff3cabd6 100644 --- a/plugins/caddy/README.md +++ b/plugins/caddy/README.md @@ -4,6 +4,11 @@ Caddy Module: http.handlers.cache Development repository of the caddy cache-handler module. This is a distributed HTTP cache module for Caddy based on [Souin](https://github.com/darkweak/souin) cache. +> [!WARNING] +> Since `v1.7.0` Souin implements only one storage. If you need a specific storage you have to take it from [the storages repository](https://github.com/darkweak/storages) and add it either in your code, during the build otherwise. +(e.g. with otter using caddy) You have to build your caddy module with the desired storage `xcaddy build --with github.com/darkweak/souin/plugins/caddy --with github.com/darkweak/storages/otter/caddy` and configure otter in your Caddyfile/JSON configuration file. +See the [documentation about the storages](https://docs.souin.io/docs/storages) + ## Features * [RFC 7234](https://httpwg.org/specs/rfc7234.html) compliant HTTP Cache. diff --git a/plugins/souin/storages/storages.go b/plugins/souin/storages/storages.go index 40d7e3400..5cbc43247 100644 --- a/plugins/souin/storages/storages.go +++ b/plugins/souin/storages/storages.go @@ -15,7 +15,7 @@ import ( "go.uber.org/zap/zapcore" ) -type factory func(badgerConfiguration core.CacheProvider, logger *zap.Logger, stale time.Duration) (core.Storer, error) +type factory func(providerConfiguration core.CacheProvider, logger *zap.Logger, stale time.Duration) (core.Storer, error) func isProviderEmpty(p configurationtypes.CacheProvider) bool { return p.Configuration == nil && p.Path == "" && p.URL == ""