A lightweight, high-performance in-memory cache HTTP service written in Go. It exposes a small REST API for storing, retrieving, deleting, and inspecting cache entries, backed by FreeCache and served via Gin.
- In-memory key/value cache powered by FreeCache (no external dependencies)
- RESTful HTTP API built on Gin
- Per-entry TTL (or "never expire" when TTL is
0) - Hit / miss / eviction / expiration statistics
- Auto-generates a default
config.ymlon first run - Single static binary, no DB required
WinnerProxy/
├── main.go # entrypoint
├── config/config.go # YAML config loader
├── internal/
│ ├── cache/freecache.go # FreeCache wrapper
│ ├── handler/handler.go # HTTP handlers
│ └── router/router.go # route registration
├── config.yml # generated on first run
├── go.mod
└── go.sum
- Go 1.26.4 or later
# Build a static binary into ./build
go build -o build/winnerproxy .
# Run from the directory where config.yml lives (the binary
# loads config.yml from the same folder as the executable)
./build/winnerproxy On first launch, WinnerProxy writes a default config.yml next to the executable if one is not present, then listens on the configured address.
config.yml is read from the directory containing the executable. Defaults:
addr: ":2779" # HTTP listen address
cache_size: 104857600 # FreeCache size in bytes (100 MB)Notes:
cache_sizehas a minimum of 512 KB; smaller values are rounded up by FreeCache.- Missing or unreadable config files fall back to defaults.
Base URL: http://<addr>
GET /health
Response 200 OK:
{ "status": "ok" }GET /cache/:key
200 OK— returns the raw value asapplication/octet-stream404 Not Found— key missing
POST /cache
Content-Type: application/json
Request body:
{
"key": "user:42",
"value": "alice",
"ttl_seconds": 60
}ttl_seconds: 0means the entry never expires.- Response
200 OK:{ "key": "user:42", "ttl_seconds": 60, "expires_at": "2026-07-03T12:34:56Z" }
DELETE /cache/:key
Response 200 OK:
{ "key": "user:42", "deleted": true }GET /cache/stats
Response 200 OK:
{
"hit_count": 12,
"miss_count": 3,
"lookup_count": 15,
"hit_rate": 0.8,
"entry_count": 7,
"overwrite_count": 1,
"evacuate_count": 0,
"expired_count": 0
}# Set a value (60s TTL)
curl -X POST http://localhost:2779/cache \
-H 'Content-Type: application/json' \
-d '{"key":"hello","value":"world","ttl_seconds":60}'
# Get it back
curl http://localhost:2779/cache/hello
# Inspect stats
curl http://localhost:2779/cache/stats
# Delete it
curl -X DELETE http://localhost:2779/cache/helloSee LICENSE.