feat: embed frontend in Go binary
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
24
main.go
24
main.go
@@ -1,10 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"embed"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
@@ -15,6 +19,9 @@ import (
|
|||||||
"gitm/internal/sync"
|
"gitm/internal/sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed all:web/dist
|
||||||
|
var webFS embed.FS
|
||||||
|
|
||||||
var (
|
var (
|
||||||
flagAddr = flag.String("addr", "", "Listen address")
|
flagAddr = flag.String("addr", "", "Listen address")
|
||||||
flagDataDir = flag.String("data", "", "Data directory")
|
flagDataDir = flag.String("data", "", "Data directory")
|
||||||
@@ -90,6 +97,23 @@ func runInitMode() {
|
|||||||
func runServer(cfg *config.Config, engine *sync.Engine) error {
|
func runServer(cfg *config.Config, engine *sync.Engine) error {
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
|
|
||||||
|
// Serve embedded frontend
|
||||||
|
distFS, err := fs.Sub(webFS, "web/dist")
|
||||||
|
if err == nil {
|
||||||
|
// Serve assets
|
||||||
|
r.StaticFS("/assets", http.FS(distFS))
|
||||||
|
// SPA fallback - serve index.html for non-API routes
|
||||||
|
r.NoRoute(func(c *gin.Context) {
|
||||||
|
if !strings.HasPrefix(c.Request.URL.Path, "/api") {
|
||||||
|
data, _ := webFS.ReadFile("web/dist/index.html")
|
||||||
|
c.Data(http.StatusOK, "text/html; charset=utf-8", data)
|
||||||
|
} else {
|
||||||
|
c.JSON(http.StatusNotFound, gin.H{"error": "Not found"})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
api := r.Group("/api")
|
api := r.Group("/api")
|
||||||
{
|
{
|
||||||
api.POST("/login", handler.HandleLogin)
|
api.POST("/login", handler.HandleLogin)
|
||||||
|
|||||||
Reference in New Issue
Block a user