diff --git a/server/static/static.go b/server/static/static.go index b5052521..f26233d4 100644 --- a/server/static/static.go +++ b/server/static/static.go @@ -9,6 +9,7 @@ import ( "os" "strings" + "github.com/OpenListTeam/OpenList/v4/drivers/base" "github.com/OpenListTeam/OpenList/v4/internal/conf" "github.com/OpenListTeam/OpenList/v4/internal/setting" "github.com/OpenListTeam/OpenList/v4/pkg/utils" @@ -19,88 +20,127 @@ import ( var static fs.FS func initStatic() { + utils.Log.Debug("Initializing static file system...") if conf.Conf.DistDir == "" { dist, err := fs.Sub(public.Public, "dist") if err != nil { - utils.Log.Fatalf("failed to read dist dir") + utils.Log.Fatalf("failed to read dist dir: %v", err) } static = dist + utils.Log.Debug("Using embedded dist directory") return } static = os.DirFS(conf.Conf.DistDir) + utils.Log.Infof("Using custom dist directory: %s", conf.Conf.DistDir) +} + +func replaceStrings(content string, replacements map[string]string) string { + for old, new := range replacements { + content = strings.Replace(content, old, new, 1) + } + return content } func initIndex() { - indexFile, err := static.Open("index.html") - if err != nil { - if errors.Is(err, fs.ErrNotExist) { - utils.Log.Fatalf("index.html not exist, you may forget to put dist of frontend to public/dist") - } - utils.Log.Fatalf("failed to read index.html: %v", err) - } - defer func() { - _ = indexFile.Close() - }() - index, err := io.ReadAll(indexFile) - if err != nil { - utils.Log.Fatalf("failed to read dist/index.html") - } - conf.RawIndexHtml = string(index) + utils.Log.Debug("Initializing index.html...") siteConfig := getSiteConfig() + if conf.Conf.DistDir != "" || (conf.Conf.Cdn != "" && (conf.WebVersion == "" || conf.WebVersion == "beta" || conf.WebVersion == "dev")) { + utils.Log.Infof("Fetching index.html from CDN: %s/index.html...", conf.Conf.Cdn) + resp, err := base.RestyClient.R(). + SetHeader("Accept", "text/html"). + Get(fmt.Sprintf("%s/index.html", siteConfig.Cdn)) + if err != nil { + utils.Log.Fatalf("failed to fetch index.html from CDN: %v", err) + } + if resp.StatusCode() != http.StatusOK { + utils.Log.Fatalf("failed to fetch index.html from CDN, status code: %d", resp.StatusCode()) + } + conf.RawIndexHtml = string(resp.Body()) + utils.Log.Info("Successfully fetched index.html from CDN") + } else { + utils.Log.Debug("Reading index.html from static files system...") + indexFile, err := static.Open("index.html") + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + utils.Log.Fatalf("index.html not exist, you may forget to put dist of frontend to public/dist") + } + utils.Log.Fatalf("failed to read index.html: %v", err) + } + defer func() { + _ = indexFile.Close() + }() + index, err := io.ReadAll(indexFile) + if err != nil { + utils.Log.Fatalf("failed to read dist/index.html") + } + conf.RawIndexHtml = string(index) + utils.Log.Debug("Successfully read index.html from static files system") + } + utils.Log.Debug("Replacing placeholders in index.html...") replaceMap := map[string]string{ "cdn: undefined": fmt.Sprintf("cdn: '%s'", siteConfig.Cdn), "base_path: undefined": fmt.Sprintf("base_path: '%s'", siteConfig.BasePath), } - for k, v := range replaceMap { - conf.RawIndexHtml = strings.Replace(conf.RawIndexHtml, k, v, 1) - } + conf.RawIndexHtml = replaceStrings(conf.RawIndexHtml, replaceMap) UpdateIndex() } func UpdateIndex() { + utils.Log.Debug("Updating index.html with settings...") favicon := setting.GetStr(conf.Favicon) title := setting.GetStr(conf.SiteTitle) customizeHead := setting.GetStr(conf.CustomizeHead) customizeBody := setting.GetStr(conf.CustomizeBody) mainColor := setting.GetStr(conf.MainColor) - conf.ManageHtml = conf.RawIndexHtml + utils.Log.Debug("Applying replacements for default pages...") replaceMap1 := map[string]string{ "https://cdn.oplist.org/gh/OpenListTeam/Logo@main/logo.svg": favicon, "Loading...": title, "main_color: undefined": fmt.Sprintf("main_color: '%s'", mainColor), } - for k, v := range replaceMap1 { - conf.ManageHtml = strings.Replace(conf.ManageHtml, k, v, 1) - } - conf.IndexHtml = conf.ManageHtml + conf.ManageHtml = replaceStrings(conf.RawIndexHtml, replaceMap1) + utils.Log.Debug("Applying replacements for manage pages...") replaceMap2 := map[string]string{ "": customizeHead, "": customizeBody, } - for k, v := range replaceMap2 { - conf.IndexHtml = strings.Replace(conf.IndexHtml, k, v, 1) - } + conf.IndexHtml = replaceStrings(conf.ManageHtml, replaceMap2) + utils.Log.Debug("Index.html update completed") } func Static(r *gin.RouterGroup, noRoute func(handlers ...gin.HandlerFunc)) { + utils.Log.Debug("Setting up static routes...") initStatic() initIndex() folders := []string{"assets", "images", "streamer", "static"} - r.Use(func(c *gin.Context) { - for i := range folders { - if strings.HasPrefix(c.Request.RequestURI, fmt.Sprintf("/%s/", folders[i])) { - c.Header("Cache-Control", "public, max-age=15552000") + if conf.Conf.Cdn == "" { + utils.Log.Debug("Setting up static file serving...") + r.Use(func(c *gin.Context) { + for _, folder := range folders { + if strings.HasPrefix(c.Request.RequestURI, fmt.Sprintf("/%s/", folder)) { + c.Header("Cache-Control", "public, max-age=15552000") + } } + }) + for _, folder := range folders { + sub, err := fs.Sub(static, folder) + if err != nil { + utils.Log.Fatalf("can't find folder: %s", folder) + } + utils.Log.Debugf("Setting up route for folder: %s", folder) + r.StaticFS(fmt.Sprintf("/%s/", folder), http.FS(sub)) } - }) - for i, folder := range folders { - sub, err := fs.Sub(static, folder) - if err != nil { - utils.Log.Fatalf("can't find folder: %s", folder) + } else { + // Ensure static file redirected to CDN + for _, folder := range folders { + r.GET(fmt.Sprintf("/%s/*filepath", folder), func(c *gin.Context) { + filepath := c.Param("filepath") + c.Redirect(http.StatusFound, fmt.Sprintf("%s/%s%s", conf.Conf.Cdn, folder, filepath)) + }) } - r.StaticFS(fmt.Sprintf("/%s/", folders[i]), http.FS(sub)) } + utils.Log.Debug("Setting up catch-all route...") noRoute(func(c *gin.Context) { if c.Request.Method != "GET" && c.Request.Method != "POST" { c.Status(405)