Skip to content

Commit 5035e9f

Browse files
committed
Rewrite full compatibility
1 parent 728a505 commit 5035e9f

263 files changed

Lines changed: 28547 additions & 8008 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ jobs:
3737
push: true
3838
file: ./Dockerfile-prod
3939
tags: |
40-
darkweak/souin:latest
41-
darkweak/souin:${{ env.RELEASE_VERSION }}
40+
darkweak/souin:latest-full
41+
darkweak/souin:${{ env.RELEASE_VERSION }}-full
4242
generate-artifacts:
4343
name: Generate cross-platform builds
4444
runs-on: ubuntu-latest

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ x-networks: &networks
184184
185185
services:
186186
souin:
187-
image: darkweak/souin:latest
187+
image: darkweak/souin:latest-full
188188
ports:
189189
- 80:80
190190
- 443:443

cache/coalescing/requestCoalescing_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func commonInitializer() (*httptest.ResponseRecorder, *http.Request, *types.Retr
1616
regexpUrls := helpers.InitializeRegexp(c)
1717
retriever := &types.RetrieverResponseProperties{
1818
Configuration: c,
19-
Provider: prs,
19+
Providers: prs,
2020
MatchedURL: tests.GetMatchedURL(tests.PATH),
2121
RegexpUrls: regexpUrls,
2222
}

cache/providers/abstractProvider.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,32 @@ import (
55
"github.com/darkweak/souin/configurationtypes"
66
)
77

8+
func contains(s []string, e string) bool {
9+
for _, a := range s {
10+
if a == e {
11+
return true
12+
}
13+
}
14+
return false
15+
}
16+
817
// InitializeProvider allow to generate the providers array according to the configuration
9-
func InitializeProvider(configuration configurationtypes.AbstractConfigurationInterface) types.AbstractProviderInterface {
10-
r, _ := RistrettoConnectionFactory(configuration)
11-
return r
18+
func InitializeProvider(configuration configurationtypes.AbstractConfigurationInterface) map[string]types.AbstractProviderInterface {
19+
providers := make(map[string]types.AbstractProviderInterface)
20+
if len(configuration.GetDefaultCache().Providers) == 0 || contains(configuration.GetDefaultCache().Providers, "all") {
21+
redis, _ := RedisConnectionFactory(configuration)
22+
providers["redis"] = redis
23+
ristretto, _ := RistrettoConnectionFactory(configuration)
24+
providers["ristretto"] = ristretto
25+
} else {
26+
if contains(configuration.GetDefaultCache().Providers, "redis") {
27+
redis, _ := RedisConnectionFactory(configuration)
28+
providers["redis"] = redis
29+
}
30+
if contains(configuration.GetDefaultCache().Providers, "ristretto") {
31+
ristretto, _ := RistrettoConnectionFactory(configuration)
32+
providers["ristretto"] = ristretto
33+
}
34+
}
35+
return providers
1236
}

cache/providers/abstractProvider_test.go

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,70 @@
11
package providers
22

33
import (
4+
"github.com/darkweak/souin/configuration"
5+
"github.com/darkweak/souin/configurationtypes"
46
"github.com/darkweak/souin/errors"
57
"github.com/darkweak/souin/helpers"
68
"github.com/darkweak/souin/tests"
9+
"log"
10+
"regexp"
711
"testing"
812
)
913

14+
func MockConfiguration() configurationtypes.AbstractConfigurationInterface {
15+
var config configuration.Configuration
16+
e := config.Parse([]byte(`
17+
default_cache:
18+
headers:
19+
- Authorization
20+
port:
21+
web: 80
22+
tls: 443
23+
redis:
24+
url: 'redis:6379'
25+
regex:
26+
exclude: 'ARegexHere'
27+
ttl: 1000
28+
reverse_proxy_url: 'http://traefik'
29+
ssl_providers:
30+
- traefik
31+
urls:
32+
'domain.com/':
33+
ttl: 1000
34+
headers:
35+
- Authorization
36+
'mysubdomain.domain.com':
37+
ttl: 50
38+
headers:
39+
- Authorization
40+
- 'Content-Type'
41+
`))
42+
if e != nil {
43+
log.Fatal(e)
44+
}
45+
return &config
46+
}
47+
48+
func MockInitializeRegexp(configurationInstance configurationtypes.AbstractConfigurationInterface) regexp.Regexp {
49+
u := ""
50+
for k := range configurationInstance.GetUrls() {
51+
if "" != u {
52+
u += "|"
53+
}
54+
u += "(" + k + ")"
55+
}
56+
57+
return *regexp.MustCompile(u)
58+
}
59+
1060
func TestInitializeProvider(t *testing.T) {
1161
c := tests.MockConfiguration()
12-
p := InitializeProvider(c)
13-
err := p.Init()
14-
if nil != err {
15-
errors.GenerateError(t, "Init shouldn't crash")
62+
ps := InitializeProvider(c)
63+
for _, p := range ps {
64+
err := p.Init()
65+
if nil != err {
66+
errors.GenerateError(t, "Init shouldn't crash")
67+
}
1668
}
1769
}
1870

cache/providers/redisProvider.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package providers
2+
3+
import (
4+
t "github.com/darkweak/souin/configurationtypes"
5+
redis "github.com/go-redis/redis/v8"
6+
"strconv"
7+
"time"
8+
)
9+
10+
// Redis provider type
11+
type Redis struct {
12+
*redis.Client
13+
t.AbstractConfigurationInterface
14+
}
15+
16+
// RedisConnectionFactory function create new Redis instance
17+
func RedisConnectionFactory(configuration t.AbstractConfigurationInterface) (*Redis, error) {
18+
return &Redis{
19+
redis.NewClient(&redis.Options{
20+
Addr: configuration.GetDefaultCache().Redis.URL,
21+
DB: 0,
22+
Password: "",
23+
}),
24+
configuration,
25+
}, nil
26+
}
27+
28+
// Get method returns the populated response if exists, empty response then
29+
func (provider *Redis) Get(key string) []byte {
30+
val2, err := provider.Client.Get(provider.Context(), key).Result()
31+
32+
if err != nil {
33+
return []byte{}
34+
}
35+
36+
return []byte(val2)
37+
}
38+
39+
// Set method will store the response in Redis provider
40+
func (provider *Redis) Set(key string, value []byte, url t.URL, duration time.Duration) {
41+
if duration == 0 {
42+
ttl, _ := strconv.Atoi(url.TTL)
43+
duration = time.Duration(ttl)*time.Second
44+
}
45+
46+
err := provider.Client.Set(provider.Context(), key, string(value), duration).Err()
47+
if err != nil {
48+
panic(err)
49+
}
50+
}
51+
52+
// Delete method will delete the response in Redis provider if exists corresponding to key param
53+
func (provider *Redis) Delete(key string) {
54+
provider.Do(provider.Context(), "del", key)
55+
}
56+
57+
// Init method will
58+
func (provider *Redis) Init() error {
59+
return nil
60+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package providers
2+
3+
import (
4+
"fmt"
5+
"github.com/darkweak/souin/cache/types"
6+
"github.com/darkweak/souin/tests"
7+
"testing"
8+
"time"
9+
10+
"github.com/darkweak/souin/configurationtypes"
11+
"github.com/darkweak/souin/errors"
12+
)
13+
14+
const REDISVALUE = "My first data"
15+
16+
func getRedisClientAndMatchedURL(key string) (types.AbstractProviderInterface, configurationtypes.URL) {
17+
return tests.GetCacheProviderClientAndMatchedURL(key, func(configurationInterface configurationtypes.AbstractConfigurationInterface) (types.AbstractProviderInterface, error) {
18+
provider, _ := RedisConnectionFactory(configurationInterface)
19+
20+
return provider, nil
21+
})
22+
}
23+
24+
func TestIShouldBeAbleToReadAndWriteDataInRedis(t *testing.T) {
25+
client, u := getRedisClientAndMatchedURL("Test")
26+
client.Set("Test", []byte(REDISVALUE), u, time.Duration(10)*time.Second)
27+
res := client.Get("Test")
28+
if REDISVALUE != string(res) {
29+
errors.GenerateError(t, fmt.Sprintf("%s not corresponding to %s", res, REDISVALUE))
30+
}
31+
}
32+
33+
func TestRedis_GetRequestInCache(t *testing.T) {
34+
client, _ := getRedisClientAndMatchedURL(NONEXISTENTKEY)
35+
res := client.Get(NONEXISTENTKEY)
36+
if string(res) != "" {
37+
errors.GenerateError(t, fmt.Sprintf("Key %s should not exist", NONEXISTENTKEY))
38+
}
39+
}
40+
41+
func TestRedis_SetRequestInCache_OneByte(t *testing.T) {
42+
client, u := getRedisClientAndMatchedURL(BYTEKEY)
43+
client.Set(BYTEKEY, []byte{65}, u, time.Duration(20) * time.Second)
44+
}
45+
46+
func TestRedis_SetRequestInCache_TTL(t *testing.T) {
47+
key := "MyEmptyKey"
48+
client, matchedURL := getRedisClientAndMatchedURL(key)
49+
nv := []byte("Hello world")
50+
setValueThenVerify(client, key, nv, matchedURL, time.Duration(20) * time.Second, t)
51+
}
52+
53+
func TestRedis_SetRequestInCache_NoTTL(t *testing.T) {
54+
client, matchedURL := getRedisClientAndMatchedURL(BYTEKEY)
55+
nv := []byte("New value")
56+
setValueThenVerify(client, BYTEKEY, nv, matchedURL, 0, t)
57+
}
58+
59+
func TestRedis_DeleteRequestInCache(t *testing.T) {
60+
client, _ := RedisConnectionFactory(tests.MockConfiguration())
61+
client.Delete(BYTEKEY)
62+
time.Sleep(1 * time.Second)
63+
if 0 < len(client.Get(BYTEKEY)) {
64+
errors.GenerateError(t, fmt.Sprintf("Key %s should not exist", BYTEKEY))
65+
}
66+
}
67+
68+
func TestRedis_Init(t *testing.T) {
69+
client, _ := RedisConnectionFactory(tests.MockConfiguration())
70+
err := client.Init()
71+
72+
if nil != err {
73+
errors.GenerateError(t, "Impossible to init Redis provider")
74+
}
75+
}

cache/providers/ristrettoProvider_test.go

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package providers
22

33
import (
44
"fmt"
5+
"github.com/darkweak/souin/cache/types"
56
"github.com/darkweak/souin/tests"
67
"testing"
78

@@ -14,20 +15,12 @@ const RISTRETTOVALUE = "My first data"
1415
const BYTEKEY = "MyByteKey"
1516
const NONEXISTENTKEY = "NonexistentKey"
1617

17-
func getRistrettoClientAndMatchedURL(key string) (*Ristretto, configurationtypes.URL) {
18-
config := tests.MockConfiguration()
19-
client, _ := RistrettoConnectionFactory(config)
20-
regexpUrls := tests.MockInitializeRegexp(config)
21-
regexpURL := regexpUrls.FindString(key)
22-
matchedURL := configurationtypes.URL{
23-
TTL: config.GetDefaultCache().TTL,
24-
Headers: config.GetDefaultCache().Headers,
25-
}
26-
if "" != regexpURL {
27-
matchedURL = config.GetUrls()[regexpURL]
28-
}
18+
func getRistrettoClientAndMatchedURL(key string) (types.AbstractProviderInterface, configurationtypes.URL) {
19+
return tests.GetCacheProviderClientAndMatchedURL(key, func(configurationInterface configurationtypes.AbstractConfigurationInterface) (types.AbstractProviderInterface, error) {
20+
provider, _ := RistrettoConnectionFactory(configurationInterface)
2921

30-
return client, matchedURL
22+
return provider, nil
23+
})
3124
}
3225

3326
func TestRistrettoConnectionFactory(t *testing.T) {
@@ -82,15 +75,15 @@ func TestRistretto_GetSetRequestInCache_OneByte(t *testing.T) {
8275
}
8376
}
8477

85-
func verifyNewValueAfterSet(client *Ristretto, key string, value []byte, t *testing.T) {
78+
func verifyNewValueAfterSet(client types.AbstractProviderInterface, key string, value []byte, t *testing.T) {
8679
newValue := client.Get(key)
8780

8881
if len(newValue) != len(value) {
8982
errors.GenerateError(t, fmt.Sprintf("Key %s should be equals to %s, %s provided", key, value, newValue))
9083
}
9184
}
9285

93-
func setValueThenVerify(client *Ristretto, key string, value []byte, matchedURL configurationtypes.URL, ttl time.Duration, t *testing.T) {
86+
func setValueThenVerify(client types.AbstractProviderInterface, key string, value []byte, matchedURL configurationtypes.URL, ttl time.Duration, t *testing.T) {
9487
client.Set(key, value, matchedURL, ttl)
9588
time.Sleep(1 * time.Second)
9689
verifyNewValueAfterSet(client, key, value, t)

0 commit comments

Comments
 (0)