Skip to content

Commit

Permalink
Rewrite full compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
darkweak committed Mar 18, 2021
1 parent 570a21a commit 40566a5
Show file tree
Hide file tree
Showing 448 changed files with 428 additions and 188,195 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ jobs:
push: true
file: ./Dockerfile-prod
tags: |
darkweak/souin:latest
darkweak/souin:${{ env.RELEASE_VERSION }}
darkweak/souin:latest-full
darkweak/souin:${{ env.RELEASE_VERSION }}-full
generate-artifacts:
name: Generate cross-platform builds
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ x-networks: &networks

services:
souin:
image: darkweak/souin:latest
image: darkweak/souin:latest-full
ports:
- 80:80
- 443:443
Expand Down
2 changes: 1 addition & 1 deletion cache/coalescing/requestCoalescing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func commonInitializer() (*httptest.ResponseRecorder, *http.Request, *types.Retr
regexpUrls := helpers.InitializeRegexp(c)
retriever := &types.RetrieverResponseProperties{
Configuration: c,
Provider: prs,
Providers: prs,
MatchedURL: tests.GetMatchedURL(tests.PATH),
RegexpUrls: regexpUrls,
}
Expand Down
30 changes: 27 additions & 3 deletions cache/providers/abstractProvider.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,32 @@ import (
"github.com/darkweak/souin/configurationtypes"
)

func contains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}

// InitializeProvider allow to generate the providers array according to the configuration
func InitializeProvider(configuration configurationtypes.AbstractConfigurationInterface) types.AbstractProviderInterface {
r, _ := RistrettoConnectionFactory(configuration)
return r
func InitializeProvider(configuration configurationtypes.AbstractConfigurationInterface) map[string]types.AbstractProviderInterface {
providers := make(map[string]types.AbstractProviderInterface)
if len(configuration.GetDefaultCache().Providers) == 0 || contains(configuration.GetDefaultCache().Providers, "all") {
redis, _ := RedisConnectionFactory(configuration)
providers["redis"] = redis
ristretto, _ := RistrettoConnectionFactory(configuration)
providers["ristretto"] = ristretto
} else {
if contains(configuration.GetDefaultCache().Providers, "redis") {
redis, _ := RedisConnectionFactory(configuration)
providers["redis"] = redis
}
if contains(configuration.GetDefaultCache().Providers, "ristretto") {
ristretto, _ := RistrettoConnectionFactory(configuration)
providers["ristretto"] = ristretto
}
}
return providers
}
60 changes: 56 additions & 4 deletions cache/providers/abstractProvider_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,70 @@
package providers

import (
"github.com/darkweak/souin/configuration"
"github.com/darkweak/souin/configurationtypes"
"github.com/darkweak/souin/errors"
"github.com/darkweak/souin/helpers"
"github.com/darkweak/souin/tests"
"log"
"regexp"
"testing"
)

func MockConfiguration() configurationtypes.AbstractConfigurationInterface {
var config configuration.Configuration
e := config.Parse([]byte(`
default_cache:
headers:
- Authorization
port:
web: 80
tls: 443
redis:
url: 'redis:6379'
regex:
exclude: 'ARegexHere'
ttl: 1000
reverse_proxy_url: 'http://traefik'
ssl_providers:
- traefik
urls:
'domain.com/':
ttl: 1000
headers:
- Authorization
'mysubdomain.domain.com':
ttl: 50
headers:
- Authorization
- 'Content-Type'
`))
if e != nil {
log.Fatal(e)
}
return &config
}

func MockInitializeRegexp(configurationInstance configurationtypes.AbstractConfigurationInterface) regexp.Regexp {
u := ""
for k := range configurationInstance.GetUrls() {
if "" != u {
u += "|"
}
u += "(" + k + ")"
}

return *regexp.MustCompile(u)
}

func TestInitializeProvider(t *testing.T) {
c := tests.MockConfiguration()
p := InitializeProvider(c)
err := p.Init()
if nil != err {
errors.GenerateError(t, "Init shouldn't crash")
ps := InitializeProvider(c)
for _, p := range ps {
err := p.Init()
if nil != err {
errors.GenerateError(t, "Init shouldn't crash")
}
}
}

Expand Down
60 changes: 60 additions & 0 deletions cache/providers/redisProvider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package providers

import (
t "github.com/darkweak/souin/configurationtypes"
redis "github.com/go-redis/redis/v8"
"strconv"
"time"
)

// Redis provider type
type Redis struct {
*redis.Client
t.AbstractConfigurationInterface
}

// RedisConnectionFactory function create new Redis instance
func RedisConnectionFactory(configuration t.AbstractConfigurationInterface) (*Redis, error) {
return &Redis{
redis.NewClient(&redis.Options{
Addr: configuration.GetDefaultCache().Redis.URL,
DB: 0,
Password: "",
}),
configuration,
}, nil
}

// Get method returns the populated response if exists, empty response then
func (provider *Redis) Get(key string) []byte {
val2, err := provider.Client.Get(provider.Context(), key).Result()

if err != nil {
return []byte{}
}

return []byte(val2)
}

// Set method will store the response in Redis provider
func (provider *Redis) Set(key string, value []byte, url t.URL, duration time.Duration) {
if duration == 0 {
ttl, _ := strconv.Atoi(url.TTL)
duration = time.Duration(ttl)*time.Second
}

err := provider.Client.Set(provider.Context(), key, string(value), duration).Err()
if err != nil {
panic(err)
}
}

// Delete method will delete the response in Redis provider if exists corresponding to key param
func (provider *Redis) Delete(key string) {
provider.Do(provider.Context(), "del", key)
}

// Init method will
func (provider *Redis) Init() error {
return nil
}
75 changes: 75 additions & 0 deletions cache/providers/redisProvider_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package providers

import (
"fmt"
"github.com/darkweak/souin/cache/types"
"github.com/darkweak/souin/tests"
"testing"
"time"

"github.com/darkweak/souin/configurationtypes"
"github.com/darkweak/souin/errors"
)

const REDISVALUE = "My first data"

func getRedisClientAndMatchedURL(key string) (types.AbstractProviderInterface, configurationtypes.URL) {
return tests.GetCacheProviderClientAndMatchedURL(key, func(configurationInterface configurationtypes.AbstractConfigurationInterface) (types.AbstractProviderInterface, error) {
provider, _ := RedisConnectionFactory(configurationInterface)

return provider, nil
})
}

func TestIShouldBeAbleToReadAndWriteDataInRedis(t *testing.T) {
client, u := getRedisClientAndMatchedURL("Test")
client.Set("Test", []byte(REDISVALUE), u, time.Duration(10)*time.Second)
res := client.Get("Test")
if REDISVALUE != string(res) {
errors.GenerateError(t, fmt.Sprintf("%s not corresponding to %s", res, REDISVALUE))
}
}

func TestRedis_GetRequestInCache(t *testing.T) {
client, _ := getRedisClientAndMatchedURL(NONEXISTENTKEY)
res := client.Get(NONEXISTENTKEY)
if string(res) != "" {
errors.GenerateError(t, fmt.Sprintf("Key %s should not exist", NONEXISTENTKEY))
}
}

func TestRedis_SetRequestInCache_OneByte(t *testing.T) {
client, u := getRedisClientAndMatchedURL(BYTEKEY)
client.Set(BYTEKEY, []byte{65}, u, time.Duration(20) * time.Second)
}

func TestRedis_SetRequestInCache_TTL(t *testing.T) {
key := "MyEmptyKey"
client, matchedURL := getRedisClientAndMatchedURL(key)
nv := []byte("Hello world")
setValueThenVerify(client, key, nv, matchedURL, time.Duration(20) * time.Second, t)
}

func TestRedis_SetRequestInCache_NoTTL(t *testing.T) {
client, matchedURL := getRedisClientAndMatchedURL(BYTEKEY)
nv := []byte("New value")
setValueThenVerify(client, BYTEKEY, nv, matchedURL, 0, t)
}

func TestRedis_DeleteRequestInCache(t *testing.T) {
client, _ := RedisConnectionFactory(tests.MockConfiguration())
client.Delete(BYTEKEY)
time.Sleep(1 * time.Second)
if 0 < len(client.Get(BYTEKEY)) {
errors.GenerateError(t, fmt.Sprintf("Key %s should not exist", BYTEKEY))
}
}

func TestRedis_Init(t *testing.T) {
client, _ := RedisConnectionFactory(tests.MockConfiguration())
err := client.Init()

if nil != err {
errors.GenerateError(t, "Impossible to init Redis provider")
}
}
23 changes: 8 additions & 15 deletions cache/providers/ristrettoProvider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package providers

import (
"fmt"
"github.com/darkweak/souin/cache/types"
"github.com/darkweak/souin/tests"
"testing"

Expand All @@ -14,20 +15,12 @@ const RISTRETTOVALUE = "My first data"
const BYTEKEY = "MyByteKey"
const NONEXISTENTKEY = "NonexistentKey"

func getRistrettoClientAndMatchedURL(key string) (*Ristretto, configurationtypes.URL) {
config := tests.MockConfiguration()
client, _ := RistrettoConnectionFactory(config)
regexpUrls := tests.MockInitializeRegexp(config)
regexpURL := regexpUrls.FindString(key)
matchedURL := configurationtypes.URL{
TTL: config.GetDefaultCache().TTL,
Headers: config.GetDefaultCache().Headers,
}
if "" != regexpURL {
matchedURL = config.GetUrls()[regexpURL]
}
func getRistrettoClientAndMatchedURL(key string) (types.AbstractProviderInterface, configurationtypes.URL) {
return tests.GetCacheProviderClientAndMatchedURL(key, func(configurationInterface configurationtypes.AbstractConfigurationInterface) (types.AbstractProviderInterface, error) {
provider, _ := RistrettoConnectionFactory(configurationInterface)

return client, matchedURL
return provider, nil
})
}

func TestRistrettoConnectionFactory(t *testing.T) {
Expand Down Expand Up @@ -82,15 +75,15 @@ func TestRistretto_GetSetRequestInCache_OneByte(t *testing.T) {
}
}

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

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

func setValueThenVerify(client *Ristretto, key string, value []byte, matchedURL configurationtypes.URL, ttl time.Duration, t *testing.T) {
func setValueThenVerify(client types.AbstractProviderInterface, key string, value []byte, matchedURL configurationtypes.URL, ttl time.Duration, t *testing.T) {
client.Set(key, value, matchedURL, ttl)
time.Sleep(1 * time.Second)
verifyNewValueAfterSet(client, key, value, t)
Expand Down

0 comments on commit 40566a5

Please sign in to comment.