html_cache.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. //go:build embed
  2. package web
  3. import (
  4. "crypto/sha256"
  5. "encoding/hex"
  6. "sync"
  7. )
  8. // HTMLCache manages the cached index.html with injected settings
  9. type HTMLCache struct {
  10. mu sync.RWMutex
  11. cachedHTML []byte
  12. etag string
  13. baseHTMLHash string // Hash of the original index.html (immutable after build)
  14. settingsVersion uint64 // Incremented when settings change
  15. }
  16. // CachedHTML represents the cache state
  17. type CachedHTML struct {
  18. Content []byte
  19. ETag string
  20. }
  21. // NewHTMLCache creates a new HTML cache instance
  22. func NewHTMLCache() *HTMLCache {
  23. return &HTMLCache{}
  24. }
  25. // SetBaseHTML initializes the cache with the base HTML template
  26. func (c *HTMLCache) SetBaseHTML(baseHTML []byte) {
  27. c.mu.Lock()
  28. defer c.mu.Unlock()
  29. hash := sha256.Sum256(baseHTML)
  30. c.baseHTMLHash = hex.EncodeToString(hash[:8]) // First 8 bytes for brevity
  31. }
  32. // Invalidate marks the cache as stale
  33. func (c *HTMLCache) Invalidate() {
  34. c.mu.Lock()
  35. defer c.mu.Unlock()
  36. c.settingsVersion++
  37. c.cachedHTML = nil
  38. c.etag = ""
  39. }
  40. // Get returns the cached HTML or nil if cache is stale
  41. func (c *HTMLCache) Get() *CachedHTML {
  42. c.mu.RLock()
  43. defer c.mu.RUnlock()
  44. if c.cachedHTML == nil {
  45. return nil
  46. }
  47. return &CachedHTML{
  48. Content: c.cachedHTML,
  49. ETag: c.etag,
  50. }
  51. }
  52. // Set updates the cache with new rendered HTML
  53. func (c *HTMLCache) Set(html []byte, settingsJSON []byte) {
  54. c.mu.Lock()
  55. defer c.mu.Unlock()
  56. c.cachedHTML = html
  57. c.etag = c.generateETag(settingsJSON)
  58. }
  59. // generateETag creates an ETag from base HTML hash + settings hash
  60. func (c *HTMLCache) generateETag(settingsJSON []byte) string {
  61. settingsHash := sha256.Sum256(settingsJSON)
  62. return `"` + c.baseHTMLHash + "-" + hex.EncodeToString(settingsHash[:8]) + `"`
  63. }