xtablo-source/go_backend/internal/spahandler/handler.go
Arthur Belleville 50ba9b340b
Modify backend
2025-03-15 08:46:51 +01:00

129 lines
3 KiB
Go

package spahandler
import (
"fmt"
"io/fs"
"net/http"
"os"
"path/filepath"
"text/template"
"github.com/olivere/vite"
"github.com/rs/zerolog/log"
"xtablo-backend/internal/frontend"
)
type handler struct {
distFS fs.FS
}
func NewHandler() *handler {
distFS, err := fs.Sub(frontend.DistFS, "dist")
if err != nil {
panic(fmt.Errorf("creating sub-filesystem for 'dist' directory: %w", err))
}
return &handler{
distFS: distFS,
}
}
func (h *handler) GetAssets() http.HandlerFunc {
return http.FileServerFS(h.distFS).ServeHTTP
}
func (h *handler) GetSpa() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var err error
defer func() {
if err != nil {
log.Err(err).Msg(err.Error())
}
}()
if r.URL.Path == "/" || r.URL.Path == "/index.html" {
viteFragment, err := vite.HTMLFragment(vite.Config{
FS: h.distFS,
IsDev: false,
})
if err != nil {
log.Err(err).Msg(err.Error())
http.Error(w, "Error instantiating vite fragment", http.StatusInternalServerError)
return
}
tmpl, err := template.New("index").Parse(indexTmpl)
if err != nil {
http.Error(w, "Error parsing template", http.StatusInternalServerError)
return
}
if err = tmpl.Execute(w, map[string]interface{}{
"Vite": viteFragment,
}); err != nil {
http.Error(w, "Error executing template", http.StatusInternalServerError)
return
}
return
}
// Serve the public files generated by Vite. By default, these files are
// referenced in the DOM with a root-relative URL format (e.g. '/file.ext').
http.ServeFileFS(w, r, h.distFS, filepath.Base(r.URL.Path))
}
}
func (h *handler) GetDevSpa() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var err error
defer func() {
if err != nil {
log.Err(err).Msg(err.Error())
}
}()
if r.URL.Path == "/" || r.URL.Path == "/index.html" {
viteFragment, err := vite.HTMLFragment(vite.Config{
FS: os.DirFS("ui"),
IsDev: true,
ViteURL: "http://localhost:5173",
ViteTemplate: vite.SvelteTs,
ViteEntry: "/src/main.ts",
})
if err != nil {
http.Error(w, "Error instantiating vite fragment", http.StatusInternalServerError)
return
}
tmpl, err := template.New("index").Parse(indexTmpl)
if err != nil {
http.Error(w, "Error parsing template", http.StatusInternalServerError)
return
}
if err = tmpl.Execute(w, map[string]interface{}{
"Vite": viteFragment,
}); err != nil {
http.Error(w, "Error executing template", http.StatusInternalServerError)
return
}
return
}
// Serve files in the public directory. By default, these files are
// referenced in the DOM with a root-relative URL format (e.g. '/file.ext').
http.ServeFileFS(w, r, os.DirFS("./public"), filepath.Base(r.URL.Path))
}
}
var indexTmpl = `<!doctype html>
<html lang="en" class="h-full scroll-smooth">
<head>
<meta charset="UTF-8" />
{{ .Vite.Tags }}
</head>
<body class="w-100">
<div id="app"></div>
</body>
</html>
`