74 lines
1.9 KiB
Go

package server
import (
"net/http"
"path/filepath"
"strings"
"github.com/gin-gonic/gin"
)
type Options struct {
UIServeDir string
TemplateDir string
StaticDir string
EnableCORS bool
}
func NewRouter(opts Options) *gin.Engine {
r := gin.New()
r.Use(gin.Logger())
r.Use(gin.Recovery())
if opts.EnableCORS {
r.Use(func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
if c.Request.Method == http.MethodOptions {
c.AbortWithStatus(http.StatusNoContent)
return
}
c.Next()
})
}
if strings.TrimSpace(opts.StaticDir) != "" {
r.Static("/static", opts.StaticDir)
}
// Do not render legacy templates; keep core frontend under /ui
api := r.Group("/api")
{
api.GET("/health", handleHealth)
api.GET("/system/status", handleSystemStatus)
api.GET("/stations", handleStations)
api.GET("/data", handleData)
api.GET("/forecast", handleForecast)
api.GET("/radar/times", handleRadarTimes)
api.GET("/radar/tiles_at", handleRadarTilesAt)
api.GET("/rain/times", handleRainTimes)
api.GET("/rain/tiles_at", handleRainTilesAt)
}
if strings.TrimSpace(opts.UIServeDir) != "" {
// Serve built Angular assets under /ui for static files
r.Static("/ui", opts.UIServeDir)
// Serve Angular index.html at root
r.GET("/", func(c *gin.Context) {
c.File(filepath.Join(opts.UIServeDir, "index.html"))
})
// Optional SPA fallback: serve index.html for non-API, non-static routes
r.NoRoute(func(c *gin.Context) {
p := c.Request.URL.Path
if strings.HasPrefix(p, "/api/") || strings.HasPrefix(p, "/static/") {
c.AbortWithStatus(http.StatusNotFound)
return
}
c.File(filepath.Join(opts.UIServeDir, "index.html"))
})
}
return r
}