Files
MrixsCraft-server/internal/templates/templates.go
Vladimir Zagainov 2f1f1ef7d6
All checks were successful
CI / lint (push) Successful in 17s
CI / test (push) Successful in 18s
CI / build (push) Successful in 18s
CI / docker (push) Successful in 1m1s
fix: embed HTML templates into binary via go:embed
Switched from runtime file-based template loading (os.Stat + ParseGlob)
to compile-time embedding (embed.FS + ParseFS). Templates are now
bundled into the binary — no need to COPY them into Docker image.

This fixes the fallback response issue where h.loaded was always false
because templates weren't present in the container filesystem.
2026-06-04 06:51:11 +03:00

93 lines
2.8 KiB
Go

// package templates handles Go html/template rendering for the website.
package templates
import (
"embed"
"html/template"
"log"
"net/http"
"gitea.mrixs.me/Mrixs/MrixsCraft-server/internal/config"
"gitea.mrixs.me/Mrixs/MrixsCraft-server/internal/database"
)
//go:embed html/*.html
var templateFS embed.FS
// pageData is passed to all templates.
type pageData struct {
Title string
Username string
UUID string
}
// Handler serves template-rendered pages.
type Handler struct {
db *database.DB
cfg *config.Config
tmpl *template.Template
}
// NewHandler creates a new templates handler and parses embedded templates.
func NewHandler(db *database.DB, cfg *config.Config) *Handler {
h := &Handler{db: db, cfg: cfg}
h.parseTemplates()
return h
}
// RegisterRoutes mounts template-rendered pages.
func (h *Handler) RegisterRoutes(mux *http.ServeMux) {
mux.HandleFunc("GET /", h.index)
mux.HandleFunc("GET /login", h.loginPage)
mux.HandleFunc("GET /register", h.registerPage)
mux.HandleFunc("GET /profile", h.profilePage)
}
// ── Page handlers ──────────────────────────────────────────────
func (h *Handler) index(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
h.render(w, "index.html", pageData{Title: "Главная"})
}
func (h *Handler) loginPage(w http.ResponseWriter, r *http.Request) {
h.render(w, "login.html", pageData{Title: "Вход"})
}
func (h *Handler) registerPage(w http.ResponseWriter, r *http.Request) {
h.render(w, "register.html", pageData{Title: "Регистрация"})
}
func (h *Handler) profilePage(w http.ResponseWriter, r *http.Request) {
h.render(w, "profile.html", pageData{Title: "Профиль"})
}
// render executes the base layout template which calls {{template "content" .}}
// to inject the named page content.
func (h *Handler) render(w http.ResponseWriter, page string, data pageData) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if h.tmpl == nil {
http.Error(w, "Templates not loaded", http.StatusInternalServerError)
return
}
if err := h.tmpl.ExecuteTemplate(w, "base.html", data); err != nil {
log.Printf("Template error (base.html → %s): %v", page, err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}
// ── Template parsing ───────────────────────────────────────────
func (h *Handler) parseTemplates() {
tmpl, err := template.New("").Funcs(template.FuncMap{}).ParseFS(templateFS, "html/*.html")
if err != nil {
log.Printf("Template parse error: %v", err)
return
}
h.tmpl = tmpl
log.Println("Loaded embedded HTML templates")
}