mirror of
https://github.com/pocket-id/pocket-id.git
synced 2025-12-06 09:13:19 +03:00
78 lines
2.1 KiB
Go
78 lines
2.1 KiB
Go
//go:build !exclude_frontend
|
|
|
|
package frontend
|
|
|
|
import (
|
|
"embed"
|
|
"fmt"
|
|
"io/fs"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
//go:embed all:dist/*
|
|
var frontendFS embed.FS
|
|
|
|
func RegisterFrontend(router *gin.Engine) error {
|
|
distFS, err := fs.Sub(frontendFS, "dist")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create sub FS: %w", err)
|
|
}
|
|
|
|
cacheMaxAge := time.Hour * 24
|
|
fileServer := NewFileServerWithCaching(http.FS(distFS), int(cacheMaxAge.Seconds()))
|
|
|
|
router.NoRoute(func(c *gin.Context) {
|
|
// Try to serve the requested file
|
|
path := strings.TrimPrefix(c.Request.URL.Path, "/")
|
|
if _, err := fs.Stat(distFS, path); os.IsNotExist(err) {
|
|
// File doesn't exist, serve index.html instead
|
|
c.Request.URL.Path = "/"
|
|
}
|
|
|
|
fileServer.ServeHTTP(c.Writer, c.Request)
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// FileServerWithCaching wraps http.FileServer to add caching headers
|
|
type FileServerWithCaching struct {
|
|
root http.FileSystem
|
|
lastModified time.Time
|
|
cacheMaxAge int
|
|
lastModifiedHeaderValue string
|
|
cacheControlHeaderValue string
|
|
}
|
|
|
|
func NewFileServerWithCaching(root http.FileSystem, maxAge int) *FileServerWithCaching {
|
|
return &FileServerWithCaching{
|
|
root: root,
|
|
lastModified: time.Now(),
|
|
cacheMaxAge: maxAge,
|
|
lastModifiedHeaderValue: time.Now().UTC().Format(http.TimeFormat),
|
|
cacheControlHeaderValue: fmt.Sprintf("public, max-age=%d", maxAge),
|
|
}
|
|
}
|
|
|
|
func (f *FileServerWithCaching) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
// Check if the client has a cached version
|
|
if ifModifiedSince := r.Header.Get("If-Modified-Since"); ifModifiedSince != "" {
|
|
ifModifiedSinceTime, err := time.Parse(http.TimeFormat, ifModifiedSince)
|
|
if err == nil && f.lastModified.Before(ifModifiedSinceTime.Add(1*time.Second)) {
|
|
// Client's cached version is up to date
|
|
w.WriteHeader(http.StatusNotModified)
|
|
return
|
|
}
|
|
}
|
|
|
|
w.Header().Set("Last-Modified", f.lastModifiedHeaderValue)
|
|
w.Header().Set("Cache-Control", f.cacheControlHeaderValue)
|
|
|
|
http.FileServer(f.root).ServeHTTP(w, r)
|
|
}
|