From a61d80ee1f320afcb5646991475e93f5df14796b Mon Sep 17 00:00:00 2001 From: Jan Bader Date: Sun, 13 Feb 2022 13:11:22 +0000 Subject: [PATCH] Implement SPA handling in Backend --- http/http.go | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/http/http.go b/http/http.go index 53870b4..ade5c22 100644 --- a/http/http.go +++ b/http/http.go @@ -1,8 +1,11 @@ package http import ( + "errors" + "io" "io/fs" "net/http" + "path" "strings" "git.javil.eu/jacob1123/budgeteer" @@ -18,6 +21,7 @@ type Handler struct { Service *postgres.Database TokenVerifier budgeteer.TokenVerifier CredentialsVerifier *bcrypt.Verifier + StaticFS http.FileSystem } const ( @@ -37,14 +41,10 @@ func (h *Handler) LoadRoutes(router *gin.Engine) { if err != nil { panic("couldn't open static files") } - staticFS := http.FS(static) + h.StaticFS = http.FS(static) router.Use(enableCachingForStaticFiles()) - router.NoRoute( - func(c *gin.Context) { - c.FileFromFS(c.Request.URL.Path, staticFS) - }, - ) + router.NoRoute(h.ServeStatic) withLogin := router.Group("") withLogin.Use(h.verifyLoginWithRedirect) @@ -81,6 +81,35 @@ func (h *Handler) LoadRoutes(router *gin.Engine) { transaction.POST("/new", h.newTransaction) transaction.POST("/:transactionid", h.newTransaction) } +func (h *Handler) ServeStatic(c *gin.Context) { + h.ServeStaticFile(c, c.Request.URL.Path) +} + +func (h *Handler) ServeStaticFile(c *gin.Context, fullPath string) { + file, err := h.StaticFS.Open(fullPath) + if errors.Is(err, fs.ErrNotExist) { + h.ServeStaticFile(c, path.Join("/", "/index.html")) + return + } + + if err != nil { + c.AbortWithError(http.StatusInternalServerError, err) + return + } + + stat, err := file.Stat() + if err != nil { + c.AbortWithError(http.StatusInternalServerError, err) + return + } + + if stat.IsDir() { + h.ServeStaticFile(c, path.Join(fullPath, "index.html")) + return + } + + http.ServeContent(c.Writer, c.Request, stat.Name(), stat.ModTime(), file.(io.ReadSeeker)) +} func enableCachingForStaticFiles() gin.HandlerFunc { return func(c *gin.Context) {