Skip to content

Commit

Permalink
feat(chore): support http-invalidation RFC as early stage (https://da…
Browse files Browse the repository at this point in the history
  • Loading branch information
darkweak committed Aug 27, 2023
1 parent 3039edb commit fe73f41
Showing 1 changed file with 97 additions and 0 deletions.
97 changes: 97 additions & 0 deletions pkg/api/souin.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"net/http"
"regexp"
"strings"

"github.com/darkweak/souin/configurationtypes"
"github.com/darkweak/souin/pkg/storage"
Expand All @@ -17,6 +18,23 @@ type SouinAPI struct {
enabled bool
storers []storage.Storer
surrogateStorage providers.SurrogateInterface
allowedMethods []string
}

type invalidationType string

const (
uriInvalidationType invalidationType = "uri"
uriPrefixInvalidationType invalidationType = "uri-prefix"
originInvalidationType invalidationType = "origin"
groupInvalidationType invalidationType = "group"
)

type invalidation struct {
Type invalidationType `json:"type"`
Selectors []string `json:"selectors"`
Groups []string `json:"groups"`
Purge bool `json:"purge"`
}

func initializeSouin(
Expand All @@ -28,11 +46,18 @@ func initializeSouin(
if basePath == "" {
basePath = "/souin"
}

allowedMethods := configuration.GetDefaultCache().GetAllowedHTTPVerbs()
if len(allowedMethods) == 0 {
allowedMethods = []string{http.MethodGet, http.MethodHead}
}

return &SouinAPI{
basePath,
configuration.GetAPI().Souin.Enable,
storers,
surrogateStorage,
allowedMethods,
}
}

Expand Down Expand Up @@ -103,6 +128,78 @@ func (s *SouinAPI) HandleRequest(w http.ResponseWriter, r *http.Request) {
res, _ = json.Marshal(s.GetAll())
}
w.Header().Set("Content-Type", "application/json")
case http.MethodPost:
var invalidator invalidation
err := json.NewDecoder(r.Body).Decode(invalidator)

Check failure on line 133 in pkg/api/souin.go

View workflow job for this annotation

GitHub Actions / Validate Go code linting

unmarshal: call of Decode passes non-pointer (govet)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}

keysToInvalidate := []string{}
switch invalidator.Type {
case groupInvalidationType:
keysToInvalidate, _ = s.surrogateStorage.Purge(http.Header{"Surrogate-Key": invalidator.Groups})
case uriPrefixInvalidationType, uriInvalidationType:
bodyKeys := []string{}
listedKeys := s.GetAll()
for _, k := range invalidator.Selectors {
if !strings.Contains(k, "//") {
rq, err := http.NewRequest(http.MethodGet, "//"+k, nil)
if err != nil {
continue
}

bodyKeys = append(bodyKeys, rq.Host+"-"+rq.URL.Path)
}
}

for _, allKey := range listedKeys {
for _, bk := range bodyKeys {
if invalidator.Type == uriInvalidationType {
if strings.Contains(allKey, bk) && strings.Contains(allKey, bk+"-") && strings.HasSuffix(allKey, bk) {
keysToInvalidate = append(keysToInvalidate, allKey)
break
}
} else {
if strings.Contains(allKey, bk) &&
(strings.Contains(allKey, bk+"-") || strings.Contains(allKey, bk+"?") || strings.Contains(allKey, bk+"/") || strings.HasSuffix(allKey, bk)) {
keysToInvalidate = append(keysToInvalidate, allKey)
break
}
}
}
}
case originInvalidationType:
bodyKeys := []string{}
listedKeys := s.GetAll()
for _, k := range invalidator.Selectors {
if !strings.Contains(k, "//") {
rq, err := http.NewRequest(http.MethodGet, "//"+k, nil)
if err != nil {
continue
}

bodyKeys = append(bodyKeys, rq.Host)
}
}

for _, allKey := range listedKeys {
for _, bk := range bodyKeys {
if strings.Contains(allKey, bk) {
keysToInvalidate = append(keysToInvalidate, allKey)
break
}
}
}
}

for _, k := range keysToInvalidate {
for _, current := range s.storers {
current.Delete(k)
}
}
w.WriteHeader(http.StatusOK)
case "PURGE":
if compile {
keysRg := regexp.MustCompile(s.GetBasePath() + "/(.+)")
Expand Down

0 comments on commit fe73f41

Please sign in to comment.