feat: self-hosted favicon resolver via /favicon/<domain>

Adds a Kafka-hosted favicon proxy at /favicon/<domain>:
- Fetches favicon.ico from the target domain
- In-memory cache with 1-hour TTL and ETag support (304 Not Modified)
- Max 64KB per favicon to prevent memory abuse
- Privacy: user browser talks to Kafka, not Google/DuckDuckGo

New "Self (Kafka)" option in the favicon service selector.
Defaults to None. No third-party requests when self is chosen.
This commit is contained in:
Franz Kafka 2026-03-23 14:35:19 +00:00
parent d0efcb0309
commit 352264509c
4 changed files with 124 additions and 4 deletions

View file

@ -90,6 +90,7 @@ func main() {
mux.HandleFunc("/healthz", h.Healthz)
mux.HandleFunc("/autocompleter", h.Autocompleter)
mux.HandleFunc("/opensearch.xml", h.OpenSearch(cfg.Server.BaseURL))
mux.HandleFunc("/favicon/", h.Favicon)
// Serve embedded static files (CSS, JS, images).
staticFS, err := views.StaticFS()