mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2025-09-19 20:26:26 +08:00
feat(static): fetch index.html from cdn for beta (#372)
* refactor(static): simplify folder iteration in Static function * feat(static): disable local static when `cdn` is set * feat(static): fetch index.html from cdn for beta * refactor(static): use RestyClient for better retrying * fix(static): add Accept header when fetching index.html from CDN * refactor(static): optimize HTML replacement * chore(static): add logging to static file system initialization * feat(static): ensure static file redirected to CDN
This commit is contained in:
@ -9,6 +9,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||||
"github.com/OpenListTeam/OpenList/v4/internal/conf"
|
"github.com/OpenListTeam/OpenList/v4/internal/conf"
|
||||||
"github.com/OpenListTeam/OpenList/v4/internal/setting"
|
"github.com/OpenListTeam/OpenList/v4/internal/setting"
|
||||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||||
@ -19,18 +20,45 @@ import (
|
|||||||
var static fs.FS
|
var static fs.FS
|
||||||
|
|
||||||
func initStatic() {
|
func initStatic() {
|
||||||
|
utils.Log.Debug("Initializing static file system...")
|
||||||
if conf.Conf.DistDir == "" {
|
if conf.Conf.DistDir == "" {
|
||||||
dist, err := fs.Sub(public.Public, "dist")
|
dist, err := fs.Sub(public.Public, "dist")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Log.Fatalf("failed to read dist dir")
|
utils.Log.Fatalf("failed to read dist dir: %v", err)
|
||||||
}
|
}
|
||||||
static = dist
|
static = dist
|
||||||
|
utils.Log.Debug("Using embedded dist directory")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
static = os.DirFS(conf.Conf.DistDir)
|
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() {
|
func initIndex() {
|
||||||
|
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")
|
indexFile, err := static.Open("index.html")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
@ -46,61 +74,73 @@ func initIndex() {
|
|||||||
utils.Log.Fatalf("failed to read dist/index.html")
|
utils.Log.Fatalf("failed to read dist/index.html")
|
||||||
}
|
}
|
||||||
conf.RawIndexHtml = string(index)
|
conf.RawIndexHtml = string(index)
|
||||||
siteConfig := getSiteConfig()
|
utils.Log.Debug("Successfully read index.html from static files system")
|
||||||
|
}
|
||||||
|
utils.Log.Debug("Replacing placeholders in index.html...")
|
||||||
replaceMap := map[string]string{
|
replaceMap := map[string]string{
|
||||||
"cdn: undefined": fmt.Sprintf("cdn: '%s'", siteConfig.Cdn),
|
"cdn: undefined": fmt.Sprintf("cdn: '%s'", siteConfig.Cdn),
|
||||||
"base_path: undefined": fmt.Sprintf("base_path: '%s'", siteConfig.BasePath),
|
"base_path: undefined": fmt.Sprintf("base_path: '%s'", siteConfig.BasePath),
|
||||||
}
|
}
|
||||||
for k, v := range replaceMap {
|
conf.RawIndexHtml = replaceStrings(conf.RawIndexHtml, replaceMap)
|
||||||
conf.RawIndexHtml = strings.Replace(conf.RawIndexHtml, k, v, 1)
|
|
||||||
}
|
|
||||||
UpdateIndex()
|
UpdateIndex()
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateIndex() {
|
func UpdateIndex() {
|
||||||
|
utils.Log.Debug("Updating index.html with settings...")
|
||||||
favicon := setting.GetStr(conf.Favicon)
|
favicon := setting.GetStr(conf.Favicon)
|
||||||
title := setting.GetStr(conf.SiteTitle)
|
title := setting.GetStr(conf.SiteTitle)
|
||||||
customizeHead := setting.GetStr(conf.CustomizeHead)
|
customizeHead := setting.GetStr(conf.CustomizeHead)
|
||||||
customizeBody := setting.GetStr(conf.CustomizeBody)
|
customizeBody := setting.GetStr(conf.CustomizeBody)
|
||||||
mainColor := setting.GetStr(conf.MainColor)
|
mainColor := setting.GetStr(conf.MainColor)
|
||||||
conf.ManageHtml = conf.RawIndexHtml
|
utils.Log.Debug("Applying replacements for default pages...")
|
||||||
replaceMap1 := map[string]string{
|
replaceMap1 := map[string]string{
|
||||||
"https://cdn.oplist.org/gh/OpenListTeam/Logo@main/logo.svg": favicon,
|
"https://cdn.oplist.org/gh/OpenListTeam/Logo@main/logo.svg": favicon,
|
||||||
"Loading...": title,
|
"Loading...": title,
|
||||||
"main_color: undefined": fmt.Sprintf("main_color: '%s'", mainColor),
|
"main_color: undefined": fmt.Sprintf("main_color: '%s'", mainColor),
|
||||||
}
|
}
|
||||||
for k, v := range replaceMap1 {
|
conf.ManageHtml = replaceStrings(conf.RawIndexHtml, replaceMap1)
|
||||||
conf.ManageHtml = strings.Replace(conf.ManageHtml, k, v, 1)
|
utils.Log.Debug("Applying replacements for manage pages...")
|
||||||
}
|
|
||||||
conf.IndexHtml = conf.ManageHtml
|
|
||||||
replaceMap2 := map[string]string{
|
replaceMap2 := map[string]string{
|
||||||
"<!-- customize head -->": customizeHead,
|
"<!-- customize head -->": customizeHead,
|
||||||
"<!-- customize body -->": customizeBody,
|
"<!-- customize body -->": customizeBody,
|
||||||
}
|
}
|
||||||
for k, v := range replaceMap2 {
|
conf.IndexHtml = replaceStrings(conf.ManageHtml, replaceMap2)
|
||||||
conf.IndexHtml = strings.Replace(conf.IndexHtml, k, v, 1)
|
utils.Log.Debug("Index.html update completed")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Static(r *gin.RouterGroup, noRoute func(handlers ...gin.HandlerFunc)) {
|
func Static(r *gin.RouterGroup, noRoute func(handlers ...gin.HandlerFunc)) {
|
||||||
|
utils.Log.Debug("Setting up static routes...")
|
||||||
initStatic()
|
initStatic()
|
||||||
initIndex()
|
initIndex()
|
||||||
folders := []string{"assets", "images", "streamer", "static"}
|
folders := []string{"assets", "images", "streamer", "static"}
|
||||||
|
if conf.Conf.Cdn == "" {
|
||||||
|
utils.Log.Debug("Setting up static file serving...")
|
||||||
r.Use(func(c *gin.Context) {
|
r.Use(func(c *gin.Context) {
|
||||||
for i := range folders {
|
for _, folder := range folders {
|
||||||
if strings.HasPrefix(c.Request.RequestURI, fmt.Sprintf("/%s/", folders[i])) {
|
if strings.HasPrefix(c.Request.RequestURI, fmt.Sprintf("/%s/", folder)) {
|
||||||
c.Header("Cache-Control", "public, max-age=15552000")
|
c.Header("Cache-Control", "public, max-age=15552000")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
for i, folder := range folders {
|
for _, folder := range folders {
|
||||||
sub, err := fs.Sub(static, folder)
|
sub, err := fs.Sub(static, folder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Log.Fatalf("can't find folder: %s", folder)
|
utils.Log.Fatalf("can't find folder: %s", folder)
|
||||||
}
|
}
|
||||||
r.StaticFS(fmt.Sprintf("/%s/", folders[i]), http.FS(sub))
|
utils.Log.Debugf("Setting up route for folder: %s", folder)
|
||||||
|
r.StaticFS(fmt.Sprintf("/%s/", folder), http.FS(sub))
|
||||||
|
}
|
||||||
|
} 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))
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils.Log.Debug("Setting up catch-all route...")
|
||||||
noRoute(func(c *gin.Context) {
|
noRoute(func(c *gin.Context) {
|
||||||
if c.Request.Method != "GET" && c.Request.Method != "POST" {
|
if c.Request.Method != "GET" && c.Request.Method != "POST" {
|
||||||
c.Status(405)
|
c.Status(405)
|
||||||
|
Reference in New Issue
Block a user