feat: api serve frontend, build workflow, router readyness

This commit is contained in:
Floriansylvain
2025-12-24 01:05:58 +01:00
parent aee595dee9
commit 4a6209a8db
13 changed files with 174 additions and 74 deletions
+5 -3
View File
@@ -32,7 +32,9 @@ type LoginCredentials struct {
Password string `json:"password" validate:"required,min=8"`
}
var shouldCookieBeSecure = os.Getenv("ENVIRONMENT") == "production"
func shouldCookieBeSecure() bool {
return os.Getenv("ENVIRONMENT") == "production"
}
func removeJwtCookie(w http.ResponseWriter) {
http.SetCookie(w, &http.Cookie{
@@ -40,7 +42,7 @@ func removeJwtCookie(w http.ResponseWriter) {
Value: "",
Expires: time.Now(),
MaxAge: -1,
Secure: shouldCookieBeSecure,
Secure: shouldCookieBeSecure(),
HttpOnly: true,
Path: "/",
})
@@ -64,7 +66,7 @@ func (h *Handler) SetJwtCookie(w *http.ResponseWriter, userId uint32) error {
Name: "jwt",
Value: tokenString,
Expires: time.Now().Add(24 * time.Hour),
Secure: shouldCookieBeSecure,
Secure: shouldCookieBeSecure(),
HttpOnly: true,
Path: "/",
})
+79
View File
@@ -0,0 +1,79 @@
package frontend
import (
"RenewCMS/internal/infrastructure/assets"
"io"
"io/fs"
"net/http"
"path/filepath"
"strings"
"time"
"github.com/go-chi/chi/v5"
)
type spaHandler struct {
staticFS fs.FS
modTime time.Time
}
func NewFrontendRouter() http.Handler {
r := chi.NewRouter()
distFS, _ := fs.Sub(assets.DistEmbed, "dist")
handler := &spaHandler{
staticFS: distFS,
modTime: time.Now(),
}
r.Get("/*", handler.ServeHTTP)
return r
}
func (h *spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
path := h.cleanPath(r.URL.Path)
if h.fileExists(path) {
h.serveAsset(w, r, path)
return
}
h.serveIndex(w, r)
}
func (h *spaHandler) cleanPath(path string) string {
return strings.TrimPrefix(filepath.Clean(path), "/")
}
func (h *spaHandler) fileExists(path string) bool {
if path == "" || path == "." {
return false
}
f, err := h.staticFS.Open(path)
if err != nil {
return false
}
defer f.Close()
return true
}
func (h *spaHandler) serveAsset(w http.ResponseWriter, r *http.Request, path string) {
w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
http.FileServer(http.FS(h.staticFS)).ServeHTTP(w, r)
}
func (h *spaHandler) serveIndex(w http.ResponseWriter, r *http.Request) {
f, err := h.staticFS.Open("index.html")
if err != nil {
http.Error(w, "Index not found", http.StatusNotFound)
return
}
defer f.Close()
content, ok := f.(io.ReadSeeker)
if !ok {
http.Error(w, "File not seekable", http.StatusInternalServerError)
return
}
w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate")
http.ServeContent(w, r, "index.html", h.modTime, content)
}