Implemented GET hash for redis (cache is currently fucked up)

This commit is contained in:
darmiel 2021-03-26 10:59:53 +01:00
parent 1b00d3f66a
commit 884db95a54
11 changed files with 159 additions and 58 deletions

View file

@ -58,7 +58,8 @@ var serveCmd = &cobra.Command{
redisAddr := viper.GetString("redis-addr")
redisPass := viper.GetString("redis-pass")
redisDB := viper.GetInt("redis-db")
redisPrefix := viper.GetString("redis-prefix")
redisPrefixVal := viper.GetString("redis-prefix-value")
redisPrefixHsh := viper.GetString("redis-prefix-hash")
if redisAddr == "" {
log.Println("WARN: Not using redis")
}
@ -71,10 +72,11 @@ var serveCmd = &cobra.Command{
s := server.NewServer(&server.YAxCConfig{
BindAddress: bind,
// Redis
RedisAddress: redisAddr,
RedisPassword: redisPass,
RedisDatabase: redisDB,
RedisPrefix: redisPrefix,
RedisAddress: redisAddr,
RedisPassword: redisPass,
RedisDatabase: redisDB,
RedisPrefixVal: redisPrefixVal,
RedisPrefixHsh: redisPrefixHsh,
// TTL
DefaultTTL: defTTL,
MinTTL: minTTL,
@ -97,7 +99,8 @@ func init() {
regStrP(serveCmd, "redis-addr", "r", "", "Redis Address")
regStr(serveCmd, "redis-pass", "", "Redis Password")
regInt(serveCmd, "redis-db", 0, "Redis Database")
regStr(serveCmd, "redis-prefix", "yaxc::", "Redis Prefix")
regStr(serveCmd, "redis-prefix-value", "yaxc::val::", "Redis Prefix (Value)")
regStr(serveCmd, "redis-prefix-hash", "yaxc::hash::", "Redis Prefix (Hash)")
// ttl
regDurP(serveCmd, "default-ttl", "t", 60*time.Second, "Default TTL")

View file

@ -0,0 +1,12 @@
package common
import (
"crypto/md5"
"fmt"
)
func Hash(text string) string {
data := []byte(text)
sum := md5.Sum(data)
return fmt.Sprintf("%x", sum)
}

View file

@ -7,4 +7,7 @@ import (
type Backend interface {
Get(key string) (string, error)
Set(key, value string, ttl time.Duration) error
GetHash(key string) (string, error)
SetHash(key, value string, ttl time.Duration) error
}

View file

@ -6,12 +6,45 @@ import (
)
type CacheBackend struct {
c *cache.Cache
errCast error
cacheVal *cache.Cache
cacheHsh *cache.Cache
errCast error
}
func (b *CacheBackend) Get(key string) (res string, err error) {
if v, ok := b.c.Get(key); ok {
return b.get(b.cacheVal, key)
}
func (b *CacheBackend) GetHash(key string) (res string, err error) {
return b.get(b.cacheHsh, key)
}
func (b *CacheBackend) Set(key, value string, ttl time.Duration) error {
log.Info("Updating cache cacheVal with key", key, "and ttl", ttl)
b.cacheVal.Set(key, value, ttl)
return nil
}
func (b *CacheBackend) SetHash(key, value string, ttl time.Duration) error {
log.Info("Updating cache cacheHsh with key", key, "and ttl", ttl)
b.cacheHsh.Set(key, value, ttl)
return nil
}
func (b *CacheBackend) get(c *cache.Cache, key string) (res string, err error) {
var cName string
if c == b.cacheVal {
cName = "val"
} else if c == b.cacheHsh {
cName = "hsh"
} else {
cName = "unknown"
}
r1, r2, r3 := c.GetWithExpiration(key)
log.Info("Requesting cache >", cName, "(", c, ")", "< with key", key, "with result:", r1, "=>", r2, "=>", r3)
if v, ok := c.Get(key); ok {
if s, ok := v.(string); ok {
return s, nil
}
@ -19,8 +52,3 @@ func (b *CacheBackend) Get(key string) (res string, err error) {
}
return "", nil
}
func (b *CacheBackend) Set(key, value string, ttl time.Duration) error {
b.c.Set(key, value, ttl)
return nil
}

View file

@ -7,13 +7,32 @@ import (
)
type RedisBackend struct {
ctx context.Context
client *redis.Client
prefix string
ctx context.Context
client *redis.Client
prefixVal string
prefixHsh string
}
func (b *RedisBackend) Get(key string) (res string, err error) {
cmd := b.client.Get(b.ctx, b.prefix+key)
return b.get(b.prefixVal, key)
}
func (b *RedisBackend) GetHash(key string) (res string, err error) {
return b.get(b.prefixHsh, key)
}
func (b *RedisBackend) Set(key, value string, ttl time.Duration) (err error) {
return b.set(b.prefixVal, key, value, ttl)
}
func (b *RedisBackend) SetHash(key, value string, ttl time.Duration) (err error) {
return b.set(b.prefixHsh, key, value, ttl)
}
///
func (b *RedisBackend) get(prefix, key string) (res string, err error) {
cmd := b.client.Get(b.ctx, prefix+key)
if err := cmd.Err(); err != nil && err != redis.Nil {
return "", err
}
@ -21,8 +40,8 @@ func (b *RedisBackend) Get(key string) (res string, err error) {
return
}
func (b *RedisBackend) Set(key, value string, ttl time.Duration) (err error) {
cmd := b.client.Set(b.ctx, b.prefix+key, value, ttl)
func (b *RedisBackend) set(prefix, key, value string, ttl time.Duration) (err error) {
cmd := b.client.Set(b.ctx, prefix+key, value, ttl)
err = cmd.Err()
return
}

View file

@ -8,4 +8,11 @@ const body = `
\/_____/ \/_/\/_/ \/_/\/_/ \/_____/
Just POST your contents to /:anywhere
`
POST /:anywhere your contents
GET /:anywhere for your contents
GET /hash/:anywhere for content hash
POST /:anywhere?ttl=3m for custom TTL
POST /:anywhere?secret=password to protect your contents
GET /:anywhere?secret=password to get protected contents`

View file

@ -1 +0,0 @@
package server

View file

@ -0,0 +1,48 @@
package server
import (
"github.com/darmiel/yaxc/internal/common"
"github.com/gofiber/fiber/v2"
)
func (s *yAxCServer) handleGetAnywhere(ctx *fiber.Ctx) (err error) {
path := ctx.Params("anywhere")
var res string
if res, err = s.Backend.Get(path); err != nil {
return
}
// Encryption
if q := ctx.Query("secret"); q != "" {
if !s.EnableEncryption {
return errEncryptionNotEnabled
}
// do not fail on error
if encrypt, err := common.Decrypt(res, q); err == nil {
res = string(encrypt)
}
}
// log.Debug(ctx.IP(), "requested", path)
if res == "" {
ctx.Status(404)
} else {
ctx.Status(200)
}
return ctx.SendString(res)
}
func (s *yAxCServer) handleGetHashAnywhere(ctx *fiber.Ctx) (err error) {
path := ctx.Params("anywhere")
var res string
if res, err = s.Backend.GetHash(path); err != nil {
return
}
if res == "" {
ctx.Status(404)
} else {
ctx.Status(200)
}
return ctx.SendString(res)
}

View file

@ -50,35 +50,13 @@ func (s *yAxCServer) handlePostAnywhere(ctx *fiber.Ctx) (err error) {
return ctx.Status(400).SendString("ERROR: " + err.Error())
}
log.Debug(ctx.IP(), "updated", path)
// Set hash
hash := common.Hash(content)
if err := s.Backend.SetHash(path, hash, 5*time.Minute); err != nil {
return ctx.Status(400).SendString("ERROR: " + err.Error())
}
log.Debug(ctx.IP(), "updated", path, "with hash", hash)
return ctx.Status(200).SendString(content)
}
func (s *yAxCServer) handleGetAnywhere(ctx *fiber.Ctx) (err error) {
path := ctx.Params("anywhere")
var res string
if res, err = s.Backend.Get(path); err != nil {
return
}
// Encryption
if q := ctx.Query("secret"); q != "" {
if !s.EnableEncryption {
return errEncryptionNotEnabled
}
// do not fail on error
if encrypt, err := common.Decrypt(res, q); err == nil {
res = string(encrypt)
}
}
log.Debug(ctx.IP(), "requested", path)
if res == "" {
ctx.Status(404)
} else {
ctx.Status(200)
}
return ctx.SendString(res)
}

View file

@ -39,6 +39,7 @@ func (s *yAxCServer) Start() {
return ctx.SendString(body)
})
s.App.Get("/hash/:anywhere", s.handleGetHashAnywhere)
s.App.Get("/:anywhere", s.handleGetAnywhere)
s.App.Post("/:anywhere", s.handlePostAnywhere)

View file

@ -28,10 +28,11 @@ type YAxCConfig struct {
// Address
BindAddress string // required
// Redis
RedisAddress string // "" -> only use cache
RedisPassword string
RedisDatabase int
RedisPrefix string
RedisAddress string // "" -> only use cache
RedisPassword string
RedisDatabase int
RedisPrefixVal string
RedisPrefixHsh string
// Timeout
DefaultTTL time.Duration // 0 -> infinite
MinTTL time.Duration // == MaxTTL -> cannot specify TTL
@ -59,8 +60,9 @@ func NewServer(cfg *YAxCConfig) (s *yAxCServer) {
if s.RedisAddress == "" {
// use cache backend
s.Backend = &CacheBackend{
c: cache.New(s.DefaultTTL, s.DefaultTTL+time.Minute),
errCast: errors.New("not a string"),
cacheVal: cache.New(s.DefaultTTL, s.DefaultTTL+time.Minute),
cacheHsh: cache.New(s.DefaultTTL, s.DefaultTTL+time.Minute),
errCast: errors.New("not a string"),
}
} else {
rb := &RedisBackend{
@ -70,7 +72,8 @@ func NewServer(cfg *YAxCConfig) (s *yAxCServer) {
Password: s.RedisPassword,
DB: s.RedisDatabase,
}),
prefix: s.RedisPrefix,
prefixVal: s.RedisPrefixVal,
prefixHsh: s.RedisPrefixHsh,
}
s.Backend = rb
// ping test