diff --git a/Dockerfile-prod b/Dockerfile-prod index 604f8f394..0bb4c8a4e 100644 --- a/Dockerfile-prod +++ b/Dockerfile-prod @@ -21,8 +21,11 @@ ADD ./plugins /app/src/github.com/darkweak/souin/plugins WORKDIR /app/src/github.com/darkweak/souin RUN go mod download +WORKDIR /app/src/github.com/darkweak/souin/plugins/souin +RUN go mod download + RUN CGO_ENABLED=0 go build -a \ - -tags netgo -ldflags '-w -extldflags "-static"' -o /app/cmd/souin ./plugins/souin + -tags netgo -ldflags '-w -extldflags "-static"' -o /app/cmd/souin . EXPOSE 80 diff --git a/docs/e2e/Souin E2E.postman_collection.json b/docs/e2e/Souin E2E.postman_collection.json index d76c04c52..fa3ff5a5c 100644 --- a/docs/e2e/Souin E2E.postman_collection.json +++ b/docs/e2e/Souin E2E.postman_collection.json @@ -3579,30 +3579,30 @@ " souinAPI: {", " listKeys: (pm, baseKey, baseUrl = '', additionalPath = '', cacheControl = '') => {", " const isCached = cacheControl == ''", - " pm.test(\"Ensure stored keys array contains only one element\", function () {", + " pm.test(\"Ensure stored keys array contains no elements\", function () {", " pm.response.to.have.status(200);", " let jsonData = pm.response.json();", - " pm.expect(jsonData).to.eql([\"GET-http-localhost:4443-/default\"]);", - " pm.expect(jsonData.length).to.eql(1);", + " pm.expect(jsonData).to.eql([]);", + " pm.expect(jsonData.length).to.eql(0);", " });", " pm.sendRequest(utils.request(baseUrl + additionalPath, cacheControl), function(_, response) {", " pm.expect(response).to.have.status(200);", " pm.sendRequest(utils.request(`${baseUrl}${utils.getVar(pm, 'souin_base_api')}${utils.getVar(pm, 'souin_api')}`, cacheControl), function (_, res) {", - " pm.test(`Check Souin API has ${isCached ? 'two' : 'none'} registered key after the first cache set`, function () {", + " pm.test(`Check Souin API has ${isCached ? 'one' : 'none'} registered key after the first cache set`, function () {", " pm.expect(res).to.have.status(200);", " let jsonData = res.json();", - " pm.expect(jsonData.length).to.eql(isCached ? 2 : 0);", + " pm.expect(jsonData.length).to.eql(isCached ? 1 : 0);", " }", " );", "", " pm.sendRequest(utils.request(baseUrl + additionalPath + 'testing', cacheControl), function() {", " pm.sendRequest(utils.request(`${baseUrl}${utils.getVar(pm, 'souin_base_api')}${utils.getVar(pm, 'souin_api')}`, cacheControl), function (_, r) {", - " pm.test(`Check Souin API has ${isCached ? 'three' : 'none'} registered key${isCached ? 's' : ''} after the second cache set`, function () {", + " pm.test(`Check Souin API has ${isCached ? 'two' : 'none'} registered key${isCached ? 's' : ''} after the second cache set`, function () {", " pm.expect(r).to.have.status(200);", " pm.expect(r).to.not.have.header(\"Cache-Status\");", " pm.expect(r).to.not.have.header(\"Age\");", " let jsonData = r.json();", - " pm.expect(jsonData.length).to.eql(isCached ? 3 : 0);", + " pm.expect(jsonData.length).to.eql(isCached ? 2 : 0);", " });", " pm.sendRequest(utils.request(`${baseUrl}${utils.getVar(pm, 'souin_base_api')}${utils.getVar(pm, 'souin_api')}/flush`, cacheControl, null, {}, 'PURGE'), function (_, r) {", " pm.expect(r).to.have.status(204);", diff --git a/pkg/api/souin.go b/pkg/api/souin.go index 6a4604ae1..661706de6 100644 --- a/pkg/api/souin.go +++ b/pkg/api/souin.go @@ -141,12 +141,13 @@ func (s *SouinAPI) listKeys(search string) []string { } var storageToInfiniteTTLMap = map[string]time.Duration{ - "BADGER": 365 * 24 * time.Hour, - "ETCD": 365 * 24 * time.Hour, - "NUTS": 0, - "OLRIC": 365 * 24 * time.Hour, - "OTTER": 365 * 24 * time.Hour, - "REDIS": -1, + "BADGER": types.OneYearDuration, + "ETCD": types.OneYearDuration, + "NUTS": 0, + "OLRIC": types.OneYearDuration, + "OTTER": types.OneYearDuration, + "REDIS": -1, + types.DefaultStorageName: types.OneYearDuration, } func (s *SouinAPI) purgeMapping() { diff --git a/pkg/storage/defaultProvider.go b/pkg/storage/defaultProvider.go index 076dd34bd..653fd203f 100644 --- a/pkg/storage/defaultProvider.go +++ b/pkg/storage/defaultProvider.go @@ -44,12 +44,26 @@ func (provider *Default) Uuid() string { // MapKeys method returns a map with the key and value func (provider *Default) 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) - keys[k] = string(value.([]byte)) + if v, ok := value.(item); ok { + if v.invalidAt.After(now) { + keys[k] = string(v.value) + } + + return true + } + 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 diff --git a/pkg/storage/types/types.go b/pkg/storage/types/types.go index eb9751bbe..e4c8603fc 100644 --- a/pkg/storage/types/types.go +++ b/pkg/storage/types/types.go @@ -8,6 +8,7 @@ import ( ) const DefaultStorageName = "DEFAULT" +const OneYearDuration = 365 * 24 * time.Hour type Storer interface { MapKeys(prefix string) map[string]string diff --git a/pkg/surrogate/providers/common.go b/pkg/surrogate/providers/common.go index e7130c39e..4dcab8332 100644 --- a/pkg/surrogate/providers/common.go +++ b/pkg/surrogate/providers/common.go @@ -32,13 +32,13 @@ const ( ) var storageToInfiniteTTLMap = map[string]time.Duration{ - "BADGER": 365 * 24 * time.Hour, - "ETCD": 365 * 24 * time.Hour, + "BADGER": types.OneYearDuration, + "ETCD": types.OneYearDuration, "NUTS": 0, - "OLRIC": 365 * 24 * time.Hour, - "OTTER": 365 * 24 * time.Hour, + "OLRIC": types.OneYearDuration, + "OTTER": types.OneYearDuration, "REDIS": -1, - types.DefaultStorageName: -1, + types.DefaultStorageName: types.OneYearDuration, } func (s *baseStorage) ParseHeaders(value string) []string {