Files
akvorado/common/http/cache.go
Vincent Bernat c610a738a1 common/http: use SHA256 to compare POST requests
In our case, this shouldn't matter. However, performance hit should be
low and maybe at some point this middleware could be used for more
sensitive stuff.
2022-12-24 11:33:58 +01:00

67 lines
1.8 KiB
Go

// SPDX-FileCopyrightText: 2022 Free Mobile
// SPDX-License-Identifier: AGPL-3.0-only
package http
import (
"bytes"
"crypto"
"io/ioutil"
"time"
cache "github.com/chenyahui/gin-cache"
"github.com/gin-gonic/gin"
"akvorado/common/reporter"
)
// CacheByRequestPath is a middleware to cache the request using path as key
func (c *Component) CacheByRequestPath(expire time.Duration) gin.HandlerFunc {
opts := c.commonCacheOptions()
opts = append(opts, cache.WithCacheStrategyByRequest(func(gc *gin.Context) (bool, cache.Strategy) {
return true, cache.Strategy{
CacheKey: gc.Request.URL.Path,
}
}))
return cache.Cache(c.cacheStore, expire, opts...)
}
// CacheByRequestBody is a middleware to cache the request using body as key
func (c *Component) CacheByRequestBody(expire time.Duration) gin.HandlerFunc {
opts := c.commonCacheOptions()
opts = append(opts, cache.WithCacheStrategyByRequest(func(gc *gin.Context) (bool, cache.Strategy) {
requestBody, err := gc.GetRawData()
gc.Request.Body = ioutil.NopCloser(bytes.NewBuffer(requestBody))
if err != nil {
return false, cache.Strategy{}
}
h := crypto.SHA256.New()
bodyHash := string(h.Sum(requestBody))
return true, cache.Strategy{
CacheKey: bodyHash,
}
}))
return cache.Cache(c.cacheStore, expire, opts...)
}
func (c *Component) commonCacheOptions() []cache.Option {
return []cache.Option{
cache.WithLogger(cacheLogger{c.r}),
cache.WithOnHitCache(func(gc *gin.Context) {
c.metrics.cacheHit.WithLabelValues(gc.Request.URL.Path, gc.Request.Method).Inc()
}),
cache.WithOnMissCache(func(gc *gin.Context) {
c.metrics.cacheMiss.WithLabelValues(gc.Request.URL.Path, gc.Request.Method).Inc()
}),
cache.WithPrefixKey("cache-"),
}
}
type cacheLogger struct {
r *reporter.Reporter
}
func (cl cacheLogger) Errorf(msg string, args ...interface{}) {
cl.r.Error().Msgf(msg, args...)
}