1. The problem I’m having:
I’m trying to purge the cache by tag / surrogate key. Caddy logs say the purge is happening, but in reality the key has not been purged.
2. Error messages and/or full log output:
I sent a request to https://localhost/souin-api/souin/surrogate_keys
with header Surrogate-Key: localhost-dev
and it was cached correctly. When I checked the /surrogate_keys
API endpoint, I saw the key was there:
> curl -k https://localhost/souin-api/souin/surrogate_keys
{"localhost-dev":",GET-https-localhost-%2Ftest-path-123"}
I tried purging the localhost-dev
surrogate key by sending PURGE to https://localhost/souin-api/souin with header Surrogate-Key: localhost-dev
:
> curl -k -X PURGE https://localhost/souin-api/souin -H "Surrogate-Key: localhost-dev" -w "\nHTTP Response Code: %{http_code}\n" -s -o /dev/null
HTTP Response Code: 204
I get the response code 204 which is expected.
Here are the Caddy logs that are logged immediately when I send the PURGE request. You can see the incoming request is logged, and then cache handler logs the purge of localhost-dev
surrogate key and all its belonging tags:
{"level":"debug","ts":"2025-04-23T14:59:31.633Z","logger":"http.handlers.cache","msg":"Incomming request &{Method:PURGE URL:/souin-api/souin Proto:HTTP/2.0 ProtoMajor:2 ProtoMinor:0 Header:map[Accept:[*/*] Surrogate-Key:[localhost-dev] User-Agent:[Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)]] Body:0x40001b1d40 GetBody:<nil> ContentLength:0 TransferEncoding:[] Close:false Host:localhost Form:map[] PostForm:map[] MultipartForm:<nil> Trailer:map[] RemoteAddr:172.17.0.1:62136 RequestURI:/souin-api/souin TLS:0x400038a9c0 Cancel:<nil> Response:<nil> Pattern: ctx:0x400088b710 pat:<nil> matches:[] otherValues:map[]}"}
{"level":"debug","ts":"2025-04-23T14:16:21.742Z","logger":"http.handlers.cache","msg":"Purge the tag localhost-dev"}
{"level":"debug","ts":"2025-04-23T14:16:21.742Z","logger":"http.handlers.cache","msg":"Purge the following tags: [ GET-https-localhost-%2Ftest-path-123]"}
But when I check, I can see the surrogate key is still there:
> curl -k https://localhost/souin-api/souin/surrogate_keys
{"localhost-dev":",GET-https-localhost-%2Ftest-path-123"}
If I send a GET request to https://localhost/test-path-123, I can see from the Cache-Status
header that we got the cache hit instead of a cache miss:
Cache-Status: my_cache; hit; ttl=296; key=GET-https-localhost-/test-path-123; detail=REDIS
But if I use the /souin-api/souin/flush
endpoint, it works and I can flush the entire cache. This is not what I want and I cannot use this. I’m mentioning it just in case it helps anyone debug this issue.
3. Caddy version:
2.10.0
4. How I installed and ran Caddy:
a. System environment:
Docker (Linux)
b. Command:
caddy run --config /etc/caddy/caddy.json
d. My complete Caddy config:
{
"apps": {
"cache": {
"api": {
"basepath": "/souin-api",
"souin": {
"basepath": "/souin",
"enable": true,
"security": false
}
},
"log_level": "debug",
"ttl": "5m",
"headers": [
"Content-Type",
"Authorization"
],
"timeout":{
"backend": "10s",
"cache": "8s"
},
"cache_name": "my_cache",
"redis": {
"found": true,
"url": "127.0.0.1:6379"
}
},
"http": {
"servers": {
"tls_terminator": {
"listen": [
":443"
],
"routes": [
{
"match": [
{
"host": [
"localhost"
]
}
],
"handle": [
{
"handler": "cache"
},
{
"handler": "headers",
"response": {
"set": {
"Surrogate-Key": ["localhost-dev"]
}
}
},
{
"handler": "static_response",
"body": "Hello, world!",
"status_code": 200
}
]
}
],
"logs": {}
}
}
},
"tls": {
"automation": {
"on_demand": {
"ask": "http://localhost:3000/caddy"
}
},
"cache": {
"capacity": 100000
}
}
},
"admin": {
"identity": {
"issuers": [
{
"module": "acme",
"email": "me@email.com"
}
]
}
},
"logging": {
"logs": {
"default": {
"level": "DEBUG",
"exclude": [
"http.log.access"
],
"writer": {
"output": "file",
"filename": "/var/log/caddy-dev/caddy.log",
"roll": true,
"roll_size_mb": 64,
"roll_keep": 20
},
"encoder": {
"format": "json",
"time_format": "iso8601"
}
},
"log0": {
"level": "DEBUG",
"writer": {
"output": "file",
"filename": "/var/log/caddy-dev/access.log",
"roll": true,
"roll_size_mb": 64,
"roll_keep": 20
},
"encoder": {
"format": "json",
"time_format": "iso8601"
},
"include": [
"http.log.access"
]
}
}
},
"storage": {
"module": "file_system",
"root": "~/caddy-dev/data"
}
}
It’s quite a weird issue, I hope someone can help me thanks guys!