package funcs import ( "io" "io/fs" "net/http" "time" "github.com/gin-gonic/gin" "github.com/rs/zerolog/log" ) func headheader(f fs.File, c *gin.Context) (nocontent bool) { stats, err := f.Stat() if c.Request.Method == "HEAD" { nocontent = true } if err != nil { log.Error().Err(err).Msg("Cant get info of file") return } c.Writer.Header().Set("Last-Modified", stats.ModTime().Format(time.RFC1123)) if t, err := time.Parse(time.RFC1123, c.GetHeader("If-Modified-Since")); stats.ModTime().After(t) && err == nil { c.Status(http.StatusNotModified) nocontent = true } else { c.Status(http.StatusOK) } return } func makeHandler(f fs.FS, name string) gin.HandlerFunc { return func(c *gin.Context) { content, err := f.Open(name) if err != nil { switch err { case fs.ErrNotExist: c.AbortWithStatus(404) default: c.AbortWithError(500, err) } return } if headheader(content, c) { return } c.Status(200) io.Copy(c.Writer, content) } } // StaticFS is an Handler for Staticfiles that doesn't use globs and uses a fs.FS func StaticFS(r gin.IRouter, files fs.FS) { if files == nil { return } fns, err := fs.ReadDir(files, ".") if err != nil { log.Error().Err(err).Msg("Error while reading this file.") return } for _, fn := range fns { if fn.IsDir() { sub, _ := fs.Sub(files, fn.Name()) StaticFS(r.Group("/"+fn.Name()), sub) } else { h := makeHandler(files, fn.Name()) if fn.Name() == "index.html" { r.GET("/", h) r.HEAD("/", h) } r.GET("/"+fn.Name(), h) r.HEAD("/"+fn.Name(), h) } } }