Skip to content

Commit a8bbc74

Browse files
committed
1.4.1 full version
1 parent 5035e9f commit a8bbc74

7 files changed

Lines changed: 89 additions & 35 deletions

File tree

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
file: ./Dockerfile-prod
3939
tags: |
4040
darkweak/souin:latest-full
41-
darkweak/souin:${{ env.RELEASE_VERSION }}-full
41+
darkweak/souin:${{ env.RELEASE_VERSION }}
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
@@ -29,7 +29,7 @@ As it's written in go, it can be deployed on any server and thanks to the docker
2929
It's RFC compatible, supporting Vary, request coalescing and other specifications related to the [RFC-7234](https://tools.ietf.org/html/rfc7234)
3030

3131
## Disclaimer
32-
If you need redis or other custom cache providers, you have to use the full-featured version. You can read the documentation, on [the full-featured branch](https://github.com/Darkweak/Souin/tree/full-version) to discover the specific parts.
32+
If you don't need redis or other custom cache providers, you can use the minimal version. You can read the documentation, on [the minimal branch](https://github.com/Darkweak/Souin) to discover the specific parts.
3333

3434
## Configuration
3535
The configuration file is stored at `/anywhere/configuration.yml`. You can edit it provided you fill at least the required parameters as shown below.

api/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
)
88

99
// Initialize contains all apis that should be enabled
10-
func Initialize(provider types.AbstractProviderInterface, c configurationtypes.AbstractConfigurationInterface) []EndpointInterface {
10+
func Initialize(providers map[string]types.AbstractProviderInterface, c configurationtypes.AbstractConfigurationInterface) []EndpointInterface {
1111
security := auth.InitializeSecurity(c)
12-
return []EndpointInterface{security, initializeSouin(provider, c, security)}
12+
return []EndpointInterface{security, initializeSouin(providers, c, security)}
1313
}

api/souin.go

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ import (
1414
type SouinAPI struct {
1515
basePath string
1616
enabled bool
17-
provider types.AbstractProviderInterface
17+
providers map[string]types.AbstractProviderInterface
1818
security *auth.SecurityAPI
1919
}
2020

21-
func initializeSouin(provider types.AbstractProviderInterface, configuration configurationtypes.AbstractConfigurationInterface, api *auth.SecurityAPI) *SouinAPI {
21+
func initializeSouin(providers map[string]types.AbstractProviderInterface, configuration configurationtypes.AbstractConfigurationInterface, api *auth.SecurityAPI) *SouinAPI {
2222
basePath := configuration.GetAPI().Souin.BasePath
2323
enabled := configuration.GetAPI().Souin.Enable
2424
var security *auth.SecurityAPI
@@ -31,28 +31,37 @@ func initializeSouin(provider types.AbstractProviderInterface, configuration con
3131
return &SouinAPI{
3232
basePath,
3333
enabled,
34-
provider,
34+
providers,
3535
security,
3636
}
3737
}
3838

3939
// BulkDelete allow user to delete multiple items with regexp
4040
func (s *SouinAPI) BulkDelete(rg *regexp.Regexp) {
41-
for _, key := range s.GetAll() {
42-
if rg.Match([]byte(key)) {
43-
s.Delete(key)
41+
for _, v := range s.GetAll() {
42+
for _, key := range v {
43+
if rg.Match([]byte(key)) {
44+
s.Delete(key)
45+
}
4446
}
4547
}
4648
}
4749

4850
// Delete will delete a record into the provider cache system and will update the Souin API if enabled
4951
func (s *SouinAPI) Delete(key string) {
50-
s.provider.Delete(key)
52+
for _, p := range s.providers {
53+
p.Delete(key)
54+
}
5155
}
5256

5357
// GetAll will retrieve all stored keys in the provider
54-
func (s *SouinAPI) GetAll() []string {
55-
return s.provider.ListKeys()
58+
func (s *SouinAPI) GetAll() map[string][]string {
59+
list := map[string][]string{}
60+
for pName, p := range s.providers {
61+
list[pName] = p.ListKeys()
62+
}
63+
64+
return list
5665
}
5766

5867
// GetBasePath will return the basepath for this resource

api/souin_test.go

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,47 +24,68 @@ func mockSouinAPI() *SouinAPI {
2424

2525
func TestSouinAPI_BulkDelete(t *testing.T) {
2626
souinMock := mockSouinAPI()
27-
souinMock.provider.Set("key", []byte("value"), tests.GetMatchedURL("key"), 20 * time.Second)
28-
souinMock.provider.Set("key2", []byte("value"), tests.GetMatchedURL("key"), 20 * time.Second)
27+
for _, provider := range souinMock.providers {
28+
provider.Set("key", []byte("value"), tests.GetMatchedURL("key"), 20 * time.Second)
29+
provider.Set("key2", []byte("value"), tests.GetMatchedURL("key"), 20 * time.Second)
30+
}
2931
time.Sleep(3 * time.Second)
30-
if len(souinMock.GetAll()) != 2 {
31-
errors.GenerateError(t, "Souin API should have a record")
32+
for _, v := range souinMock.GetAll() {
33+
if len(v) != 2 {
34+
errors.GenerateError(t, "Souin API should have a record")
35+
}
3236
}
3337
souinMock.BulkDelete(regexp.MustCompile(".+"))
3438
time.Sleep(5 * time.Second)
35-
if len(souinMock.GetAll()) != 0 {
36-
errors.GenerateError(t, "Souin API shouldn't have a record")
39+
for _, v := range souinMock.GetAll() {
40+
if len(v) != 0 {
41+
errors.GenerateError(t, "Souin API should have a record")
42+
}
3743
}
3844
}
3945

4046
func TestSouinAPI_Delete(t *testing.T) {
4147
souinMock := mockSouinAPI()
42-
souinMock.provider.Set("key", []byte("value"), tests.GetMatchedURL("key"), 20 * time.Second)
48+
for _, provider := range souinMock.providers {
49+
provider.Set("key", []byte("value"), tests.GetMatchedURL("key"), 20 * time.Second)
50+
}
4351
time.Sleep(3 * time.Second)
44-
if len(souinMock.GetAll()) != 1 {
45-
errors.GenerateError(t, "Souin API should have a record")
52+
for _, v := range souinMock.GetAll() {
53+
if len(v) != 1 {
54+
errors.GenerateError(t, "Souin API should have a record")
55+
}
4656
}
4757
souinMock.Delete("key")
4858
time.Sleep(3 * time.Second)
49-
if len(souinMock.GetAll()) == 1 {
50-
errors.GenerateError(t, "Souin API shouldn't have a record")
59+
for _, v := range souinMock.GetAll() {
60+
if len(v) == 1 {
61+
errors.GenerateError(t, "Souin API shouldn't have a record")
62+
}
5163
}
5264
}
5365

5466
func TestSouinAPI_GetAll(t *testing.T) {
5567
souinMock := mockSouinAPI()
56-
if len(souinMock.GetAll()) > 0 {
57-
errors.GenerateError(t, "Souin API don't have any record yet")
68+
for _, v := range souinMock.GetAll() {
69+
if len(v) > 0 {
70+
errors.GenerateError(t, "Souin API shouldn't have a record")
71+
}
5872
}
5973

60-
souinMock.provider.Set("key", []byte("value"), tests.GetMatchedURL("key"), 6 * time.Second)
74+
for _, provider := range souinMock.providers {
75+
provider.Set("key", []byte("value"), tests.GetMatchedURL("key"), 6 * time.Second)
76+
}
6177
time.Sleep(3 * time.Second)
62-
if len(souinMock.GetAll()) != 1 {
63-
errors.GenerateError(t, "Souin API should have a record")
78+
for _, v := range souinMock.GetAll() {
79+
if len(v) != 1 {
80+
errors.GenerateError(t, "Souin API should have a record")
81+
}
6482
}
83+
souinMock.providers["redis"].Delete("key")
6584
time.Sleep(10 * time.Second)
66-
if len(souinMock.GetAll()) == 1 {
67-
errors.GenerateError(t, "Souin API shouldn't have a record")
85+
for _, v := range souinMock.GetAll() {
86+
if len(v) == 1 {
87+
errors.GenerateError(t, "Souin API shouldn't have a record")
88+
}
6889
}
6990
}
7091

cache/providers/redisProvider.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package providers
22

33
import (
4+
"github.com/darkweak/souin/cache/keysaver"
45
t "github.com/darkweak/souin/configurationtypes"
56
redis "github.com/go-redis/redis/v8"
67
"strconv"
@@ -10,21 +11,35 @@ import (
1011
// Redis provider type
1112
type Redis struct {
1213
*redis.Client
13-
t.AbstractConfigurationInterface
14+
keySaver *keysaver.ClearKey
1415
}
1516

1617
// RedisConnectionFactory function create new Redis instance
1718
func RedisConnectionFactory(configuration t.AbstractConfigurationInterface) (*Redis, error) {
19+
var keySaver *keysaver.ClearKey
20+
if configuration.GetAPI().Souin.Enable {
21+
keySaver = keysaver.NewClearKey()
22+
//TODO handle eviction on redis
23+
}
24+
1825
return &Redis{
1926
redis.NewClient(&redis.Options{
2027
Addr: configuration.GetDefaultCache().Redis.URL,
2128
DB: 0,
2229
Password: "",
2330
}),
24-
configuration,
31+
keySaver,
2532
}, nil
2633
}
2734

35+
// ListKeys method returns the list of existing keys
36+
func (provider *Redis) ListKeys() []string {
37+
if nil != provider.keySaver {
38+
return provider.keySaver.ListKeys()
39+
}
40+
return []string{}
41+
}
42+
2843
// Get method returns the populated response if exists, empty response then
2944
func (provider *Redis) Get(key string) []byte {
3045
val2, err := provider.Client.Get(provider.Context(), key).Result()
@@ -46,12 +61,21 @@ func (provider *Redis) Set(key string, value []byte, url t.URL, duration time.Du
4661
err := provider.Client.Set(provider.Context(), key, string(value), duration).Err()
4762
if err != nil {
4863
panic(err)
64+
} else {
65+
go func() {
66+
if nil != provider.keySaver {
67+
provider.keySaver.AddKey(key)
68+
}
69+
}()
4970
}
5071
}
5172

5273
// Delete method will delete the response in Redis provider if exists corresponding to key param
5374
func (provider *Redis) Delete(key string) {
54-
provider.Do(provider.Context(), "del", key)
75+
go func() {
76+
provider.Do(provider.Context(), "del", key)
77+
provider.keySaver.DelKey(key, 0)
78+
}()
5579
}
5680

5781
// Init method will

cache/souin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func Start() {
125125
if basePathAPIS == "" {
126126
basePathAPIS = "/souin-api"
127127
}
128-
for _, endpoint := range api.Initialize(provider, c) {
128+
for _, endpoint := range api.Initialize(cacheProviders, c) {
129129
if endpoint.IsEnabled() {
130130
http.HandleFunc(fmt.Sprintf("%s%s", basePathAPIS, endpoint.GetBasePath()), endpoint.HandleRequest)
131131
http.HandleFunc(fmt.Sprintf("%s%s/", basePathAPIS, endpoint.GetBasePath()), endpoint.HandleRequest)

0 commit comments

Comments
 (0)