// Package handler contains all HTTP request handlers. package handler import ( "html/template" "log" "net/http" "os" "path/filepath" "ridgwaysystems.org/website/internal/blog" ) // Handler holds shared dependencies for all HTTP handlers. type Handler struct { store *blog.Store dataDir string templates map[string]*template.Template siteURL string devMode bool } // New creates a Handler. dataDir is the path to the data/ directory. func New(store *blog.Store, dataDir string) *Handler { h := &Handler{ store: store, dataDir: dataDir, siteURL: getenv("SITE_URL", "https://ridgwaysystems.org"), devMode: os.Getenv("DEV") == "1", } if !h.devMode { h.templates = mustLoadTemplates() } return h } func getenv(key, def string) string { if v := os.Getenv(key); v != "" { return v } return def } // tmpl returns the template set for a given name, reloading in dev mode. func (h *Handler) tmpl(name string) *template.Template { if h.devMode { return mustLoadTemplates()[name] } return h.templates[name] } func mustLoadTemplates() map[string]*template.Template { m := make(map[string]*template.Template) funcMap := template.FuncMap{ "formatDate": formatDate, "joinTags": joinTags, } base := "templates/base.html" pages := []struct { name string file string }{ {"index", "templates/index.html"}, {"blog", "templates/blog.html"}, {"post", "templates/post.html"}, {"infrastructure", "templates/infrastructure.html"}, {"status", "templates/status.html"}, {"about", "templates/about.html"}, {"admin-login", "templates/admin/login.html"}, {"admin-dashboard", "templates/admin/dashboard.html"}, {"admin-editor", "templates/admin/editor.html"}, {"admin-status", "templates/admin/status.html"}, } for _, p := range pages { t, err := template.New(filepath.Base(p.file)).Funcs(funcMap).ParseFiles(base, p.file) if err != nil { log.Fatalf("template %s: %v", p.name, err) } m[p.name] = t } return m } func (h *Handler) render(w http.ResponseWriter, name string, data any) { t := h.tmpl(name) if t == nil { http.Error(w, "template not found: "+name, http.StatusInternalServerError) return } w.Header().Set("Content-Type", "text/html; charset=utf-8") if err := t.ExecuteTemplate(w, "base", data); err != nil { log.Printf("render %s: %v", name, err) } } func (h *Handler) renderErr(w http.ResponseWriter, code int, msg string) { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.WriteHeader(code) w.Write([]byte("
" + msg + "
Home")) }