diff --git a/.gitignore b/.gitignore index 3ae8845c..eddfa4e7 100644 --- a/.gitignore +++ b/.gitignore @@ -21,12 +21,8 @@ dist/ # Dependency directories (remove the comment below to include it) # vendor/ bin/* -/alist -/alist.exe *.json -public/*.html -public/assets/ -public/public/ -/data +data/ log/ -lang/ \ No newline at end of file +lang/ +public/dist/ \ No newline at end of file diff --git a/internal/conf/config.go b/internal/conf/config.go index 5db8635c..9bfef425 100644 --- a/internal/conf/config.go +++ b/internal/conf/config.go @@ -36,7 +36,7 @@ type Config struct { Port int `json:"port" env:"PORT"` JwtSecret string `json:"jwt_secret" env:"JWT_SECRET"` // CaCheExpiration int `json:"cache_expiration" env:"CACHE_EXPIRATION"` - Assets string `json:"assets" env:"ASSETS"` + Cdn string `json:"cdn" env:"CDN"` Database Database `json:"database"` Scheme Scheme `json:"scheme"` TempDir string `json:"temp_dir" env:"TEMP_DIR"` @@ -48,7 +48,7 @@ func DefaultConfig() *Config { Address: "0.0.0.0", Port: 5244, JwtSecret: random.String(16), - Assets: "https://npm.elemecdn.com/alist-web@$version/dist", + Cdn: "", TempDir: "data/temp", Database: Database{ Type: "sqlite3", diff --git a/internal/conf/var.go b/internal/conf/var.go index 46e6d9c4..f1d7e0f9 100644 --- a/internal/conf/var.go +++ b/internal/conf/var.go @@ -22,3 +22,8 @@ var ( // StoragesLoaded loaded success if empty StoragesLoaded = false ) +var ( + RawIndexHtml string + ManageHtml string + IndexHtml string +) diff --git a/public/public.go b/public/public.go new file mode 100644 index 00000000..a158f3e0 --- /dev/null +++ b/public/public.go @@ -0,0 +1,6 @@ +package public + +import "embed" + +//go:embed dist +var Public embed.FS diff --git a/server/handles/setting.go b/server/handles/setting.go index c15150ac..00430302 100644 --- a/server/handles/setting.go +++ b/server/handles/setting.go @@ -10,6 +10,7 @@ import ( "github.com/alist-org/alist/v3/internal/sign" "github.com/alist-org/alist/v3/pkg/utils/random" "github.com/alist-org/alist/v3/server/common" + "github.com/alist-org/alist/v3/server/static" "github.com/gin-gonic/gin" ) @@ -54,6 +55,7 @@ func SaveSettings(c *gin.Context) { common.ErrorResp(c, err, 500) } else { common.SuccessResp(c) + static.UpdateIndex() } } diff --git a/server/router.go b/server/router.go index 505a3276..10a212e4 100644 --- a/server/router.go +++ b/server/router.go @@ -7,6 +7,7 @@ import ( "github.com/alist-org/alist/v3/server/common" "github.com/alist-org/alist/v3/server/handles" "github.com/alist-org/alist/v3/server/middlewares" + "github.com/alist-org/alist/v3/server/static" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" ) @@ -35,11 +36,12 @@ func Init(r *gin.Engine) { public := api.Group("/public") public.Any("/settings", handles.PublicSettings) - fs(auth.Group("/fs")) + _fs(auth.Group("/fs")) admin(auth.Group("/admin", middlewares.AuthAdmin)) if flags.Dev { dev(r.Group("/dev")) } + static.Static(r) } func admin(g *gin.RouterGroup) { @@ -107,7 +109,7 @@ func admin(g *gin.RouterGroup) { ms.POST("/send", message.HttpInstance.SendHandle) } -func fs(g *gin.RouterGroup) { +func _fs(g *gin.RouterGroup) { g.Any("/list", handles.FsList) g.Any("/get", handles.FsGet) g.Any("/dirs", handles.FsDirs) diff --git a/server/static/static.go b/server/static/static.go new file mode 100644 index 00000000..78a8ae87 --- /dev/null +++ b/server/static/static.go @@ -0,0 +1,81 @@ +package static + +import ( + "fmt" + "io/fs" + "net/http" + "net/http/pprof" + "strings" + + "github.com/alist-org/alist/v3/cmd/flags" + "github.com/alist-org/alist/v3/internal/conf" + "github.com/alist-org/alist/v3/internal/setting" + "github.com/alist-org/alist/v3/public" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" +) + +func InitIndex() { + index, err := public.Public.ReadFile("dist/index.html") + if err != nil { + log.Fatalf("failed to read index.html: %v", err) + } + conf.RawIndexHtml = string(index) + UpdateIndex() +} + +func UpdateIndex() { + cdn := conf.Conf.Cdn + basePath := setting.GetByKey(conf.BasePath) + apiUrl := setting.GetByKey(conf.ApiUrl) + favicon := setting.GetByKey(conf.Favicon) + title := setting.GetByKey(conf.SiteTitle) + customizeHead := setting.GetByKey(conf.CustomizeHead) + customizeBody := setting.GetByKey(conf.CustomizeBody) + conf.ManageHtml = conf.RawIndexHtml + replaceMap1 := map[string]string{ + "https://jsd.nn.ci/gh/alist-org/logo@main/logo.svg": favicon, + "Loading...": title, + "cdn: undefined": fmt.Sprintf("cdn: '%s'", cdn), + "base_path: undefined": fmt.Sprintf("base_path: '%s'", basePath), + "api: undefined": fmt.Sprintf("api: '%s'", apiUrl), + } + for k, v := range replaceMap1 { + conf.ManageHtml = strings.Replace(conf.ManageHtml, k, v, 1) + } + conf.IndexHtml = conf.ManageHtml + replaceMap2 := map[string]string{ + "": customizeHead, + "": customizeBody, + } + for k, v := range replaceMap2 { + conf.IndexHtml = strings.Replace(conf.IndexHtml, k, v, 1) + } +} + +func Static(r *gin.Engine) { + InitIndex() + folders := []string{"assets", "images", "streamer"} + for i, folder := range folders { + folder = "dist/" + folder + sub, err := fs.Sub(public.Public, folder) + if err != nil { + log.Fatalf("can't find folder: %s", folder) + } + r.StaticFS(fmt.Sprintf("/%s/", folders[i]), http.FS(sub)) + } + + r.NoRoute(func(c *gin.Context) { + c.Header("Content-Type", "text/html") + c.Status(200) + if strings.HasPrefix(c.Request.URL.Path, "/@manage") { + _, _ = c.Writer.WriteString(conf.ManageHtml) + } else if strings.HasPrefix(c.Request.URL.Path, "/debug/pprof") && flags.Debug { + pprof.Index(c.Writer, c.Request) + } else { + _, _ = c.Writer.WriteString(conf.IndexHtml) + } + c.Writer.Flush() + c.Writer.WriteHeaderNow() + }) +}