| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- //go:build embed
- package web
- import (
- "crypto/sha256"
- "encoding/hex"
- "sync"
- )
- // HTMLCache manages the cached index.html with injected settings
- type HTMLCache struct {
- mu sync.RWMutex
- cachedHTML []byte
- etag string
- baseHTMLHash string // Hash of the original index.html (immutable after build)
- settingsVersion uint64 // Incremented when settings change
- }
- // CachedHTML represents the cache state
- type CachedHTML struct {
- Content []byte
- ETag string
- }
- // NewHTMLCache creates a new HTML cache instance
- func NewHTMLCache() *HTMLCache {
- return &HTMLCache{}
- }
- // SetBaseHTML initializes the cache with the base HTML template
- func (c *HTMLCache) SetBaseHTML(baseHTML []byte) {
- c.mu.Lock()
- defer c.mu.Unlock()
- hash := sha256.Sum256(baseHTML)
- c.baseHTMLHash = hex.EncodeToString(hash[:8]) // First 8 bytes for brevity
- }
- // Invalidate marks the cache as stale
- func (c *HTMLCache) Invalidate() {
- c.mu.Lock()
- defer c.mu.Unlock()
- c.settingsVersion++
- c.cachedHTML = nil
- c.etag = ""
- }
- // Get returns the cached HTML or nil if cache is stale
- func (c *HTMLCache) Get() *CachedHTML {
- c.mu.RLock()
- defer c.mu.RUnlock()
- if c.cachedHTML == nil {
- return nil
- }
- return &CachedHTML{
- Content: c.cachedHTML,
- ETag: c.etag,
- }
- }
- // Set updates the cache with new rendered HTML
- func (c *HTMLCache) Set(html []byte, settingsJSON []byte) {
- c.mu.Lock()
- defer c.mu.Unlock()
- c.cachedHTML = html
- c.etag = c.generateETag(settingsJSON)
- }
- // generateETag creates an ETag from base HTML hash + settings hash
- func (c *HTMLCache) generateETag(settingsJSON []byte) string {
- settingsHash := sha256.Sum256(settingsJSON)
- return `"` + c.baseHTMLHash + "-" + hex.EncodeToString(settingsHash[:8]) + `"`
- }
|