Files
MeowBox-Core/internal/handler/static.go

98 lines
2.2 KiB
Go

package handler
import (
"embed"
"html/template"
"log"
"net/http"
"strings"
"sync"
"github.com/OmniX-Space/MeowBox-Core/internal/service"
)
//go:embed web
var webFiles embed.FS
//go:embed web/install.html
var installTemplateContent string
//go:embed web/index.html
var pageTemplateContent string
//go:embed web/httperr.html
var errorTemplateContent string
var (
installTemplate *template.Template
pageTemplate *template.Template
errorTemplate *template.Template
installOnce sync.Once
pageOnce sync.Once
errorOnce sync.Once
)
// loadInstallTemplate Initialize template (executed only once)
func loadInstallTemplate() {
installOnce.Do(func() {
var err error
installTemplate, err = template.New("install").Parse(installTemplateContent)
if err != nil {
log.Fatalf("[Error] Failed to parse install template: %v", err)
}
})
}
// loadPageTemplate Initialize template (executed only once)
func loadPageTemplate() {
pageOnce.Do(func() {
var err error
pageTemplate, err = template.New("page").Parse(pageTemplateContent)
if err != nil {
log.Fatalf("[Error] Failed to parse page template: %v", err)
}
})
}
// loadErrorTemplate Initialize template (executed only once)
func loadErrorTemplate() {
errorOnce.Do(func() {
var err error
errorTemplate, err = template.New("error").Parse(errorTemplateContent)
if err != nil {
log.Fatalf("[Error] Failed to parse error template: %v", err)
}
})
}
// StaticFileHandler Embedded static file service
func StaticFileHandler(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
// Clean path, make sure it starts with "web/"
path = strings.TrimPrefix(path, "/")
if path == "" {
ErrorHandler(w, r, http.StatusNotFound)
return
}
// Concatenate embed.FS path
filePath := "web/" + path
data, err := webFiles.ReadFile(filePath)
if err != nil {
log.Printf("[Error] Static file not found: %s", filePath)
ErrorHandler(w, r, http.StatusNotFound)
return
}
// Set Content-Type
contentType := service.GetContentType(path)
SetHeaders(w, contentType)
_, _ = w.Write(data)
}
func SetHeaders(w http.ResponseWriter, contentType string) {
w.Header().Set("Content-Type", contentType)
}