package server import ( "context" "net/http" "path" "strings" "github.com/gin-gonic/gin" "ruben/inventory2/internal/domains/accounts" "ruben/inventory2/internal/domains/authentication" etsy_platform "ruben/inventory2/internal/domains/platforms/etsy" "ruben/inventory2/internal/domains/raw_events" "ruben/inventory2/internal/logging" "ruben/inventory2/internal/server/api" templates_api "ruben/inventory2/internal/server/api/templates" "ruben/inventory2/internal/server/middleware" "ruben/inventory2/internal/server/response" "ruben/inventory2/internal/server/sse" ) type Router struct { *gin.Engine sse *sse.Queue } func NewRouter( logger *logging.Logger, contentDir string, rawEvents *raw_events.Store, accts *accounts.Store, etsy *etsy_platform.Platform, auth *authentication.Authenticator, ) *Router { authM := middleware.NewAuth( logger.WithGroup("auth-middleware"), auth, accts, ) r := gin.Default() r.Use( authM.Identify, response.HandleResponses, response.HandleErrors, ) // webpage content // top level GET is assumed to be for the home page. r.GET("/", func(c *gin.Context) { c.Redirect(http.StatusMovedPermanently, "/ui") }) templates_api.SetupRoutes( logger.WithGroup("templates"), r.Group("/ui"), "/ui", contentDir, rawEvents, accts, etsy, authM.Authenticate(), ) // non-html content: scripts, styles, images, etc r.Use(fileServer("/scripts", contentDir+"/scripts", func(c *gin.Context) { w := c.Writer w.Header().Set("Content-Type", "text/javascript") if path.Ext(c.Request.URL.Path) == ".gz" { w.Header().Set("Content-Encoding", "gzip") } })) r.Static("/styles", "./styles") r.Static("/favicon", "./favicon") r.Static("/images", "./images") // api endpoints // sse setup sq := sse.NewQueue() unp := middleware.NewUpdateNotificationPublisher( logger.WithGroup("update.notification.publisher"), sq, ).Trim("/api") api.Routes( r.Group("/api"), logger.WithGroup("/api"), authM, sq, accts, unp, rawEvents, etsy, ) return &Router{ Engine: r, sse: sq, } } func (r *Router) RunSSE(ctx context.Context) error { return r.sse.Start(ctx) } func fileServer(urlPrefix, dir string, beforeServe func(c *gin.Context)) gin.HandlerFunc { scfs := http.StripPrefix(urlPrefix, http.FileServer(http.Dir(dir))) return func(c *gin.Context) { r := c.Request if r.URL.Path == urlPrefix || strings.HasPrefix(r.URL.Path, path.Join(urlPrefix, "/")) { if beforeServe != nil { beforeServe(c) } scfs.ServeHTTP(c.Writer, r) c.Abort() } } }