redis storer silently falls back to storage.Default when configured via configuration{} without ClientName

Open Beginner friendly
#64 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
go, redis
Domain
backend, databases

Research direction

Start in redis/redis.go at redis.Factory and Uuid(), comparing the url and configuration branches with the UUID lookup described in the issue. Verify the configuration-block path uses the same default as souin and add or update coverage if the repository has relevant Redis tests; done means a password-bearing configuration block selects the Redis storer instead of storage.Default.

Written by the indexing model from the issue text.

Description

Summary

Configuring the redis storer with a configuration { ... } block and no explicit ClientName makes souin silently fall back to the in-memory storage.Default. Redis is never used, nothing errors, and the only way to notice is to read the Storer initialized: log line.

The cause is that the storer and souin compute the same uuid from different defaults.

Mechanism

storagesredis.Factory only sets ClientName in the branch taken when Configuration == nil (i.e. the url form):

https://github.com/darkweak/storages/blob/redis/caddy/v0.0.16/redis/redis.go#L52-L58

} else {
    options = redis.ClientOption{
        InitAddress: strings.Split(redisConfiguration.URL, ","),
        SelectDB:    0,
        ClientName:  "souin-redis",
    }
}

When a configuration block IS supplied, options comes from the JSON round-trip instead, so ClientName is whatever the user wrote — empty string if they wrote nothing. The storer then registers under:

// redis/redis.go Uuid()
"%s-%s-%d-%s-%s" → "redis-souin:6379--0--<stale>"

souinparseStorages independently computes the uuid it will look the storer up by, and seeds the client name with a default:

https://github.com/darkweak/souin/blob/v1.7.9/plugins/caddy/dispatch.go (redis branch)

cname := "souin-redis"
...
if d, ok := p["ClientName"]; ok { cname = fmt.Sprint(d) }
...
Uuid = fmt.Sprintf("REDIS-%s-%s-%s-%s-%s", address, username, dbname, cname, stale)

So the two sides disagree by exactly that field:

storer registers : redis-souin:6379--0--<stale>                 (ClientName empty)
souin looks up   : REDIS-redis-souin:6379--0-souin-redis-<stale>

Lookup misses → the handler keeps storage.Default → the cache silently runs in-memory.

Reproducing

cache {
    redis {
        configuration {
            InitAddress redis-souin:6379
            Password    {$REDIS_PASSWORD}
        }
    }
}

Log shows Storer initialized: []types.Storer{(*storage.Default)(...)} instead of (*redis.Redis)(...). Adding ClientName souin-redis to the block makes it load correctly.

This is easy to hit because the configuration block is the only way to supply a password — url takes a bare host:port (a redis:// DSN fails the parser with too many colons in address), and there is no sibling password directive (configuration.go's redis branch accepts only url, path, configuration). So anyone enabling redis AUTH is pushed onto exactly the path that breaks, and it breaks silently.

Suggested fix

Default ClientName in redis.Factory regardless of which branch is taken — e.g. after the unmarshal, if options.ClientName == "" { options.ClientName = "souin-redis" }. That makes the storer agree with souin's default without requiring users to know the field exists.

Alternatively souin's dispatch.go could seed cname := "" to match the zero value, but defaulting in the factory seems more robust: it keeps the name meaningful in redis CLIENT LIST output, which is presumably why it was set in the first place.

Either way, a mismatch that results in "no storer found" is worth logging rather than silently falling back — the current behaviour is indistinguishable from a working cache until you inspect the storer type.

Minor, same file

dispatch.go's redis branch does an unchecked type assertion on InitAddress:

for _, elt := range d.([]interface{}) {

Safe via the normal Caddyfile→JSON adapt path (JSON yields []interface{}), but parseRedisConfiguration in souin produces a []string for that key, so an in-memory config path would panic here. Worth a , ok guard.

Environment

  • github.com/darkweak/storages/redis/caddy@v0.0.16
  • souin v1.7.8, re-checked against v1.7.9
  • rueidis-backed redis storer, Caddy module build via xcaddy
Dominant language
Go
Stars
17
Forks
18
Avg merge
14d 10h
Merged PRs (30d)
1

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from darkweak/storages

All issues in darkweak/storages

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.