diff --git a/api/server/router/router.go b/api/server/router/router.go index 20a5c20d..c7540bc4 100644 --- a/api/server/router/router.go +++ b/api/server/router/router.go @@ -17,6 +17,7 @@ limitations under the License. package router import ( + "embed" "net/http" "github.com/gin-gonic/gin" @@ -36,10 +37,14 @@ import ( "github.com/caoyingjunz/pixiu/api/server/router/tenant" "github.com/caoyingjunz/pixiu/api/server/router/user" "github.com/caoyingjunz/pixiu/cmd/app/options" + "github.com/caoyingjunz/pixiu/pkg/static" ) type RegisterFunc func(o *options.Options) +//go:embed static +var EmbedFS embed.FS + func InstallRouters(o *options.Options) { fs := []RegisterFunc{ middleware.InstallMiddlewares, @@ -54,6 +59,7 @@ func InstallRouters(o *options.Options) { install(o, fs...) + o.HttpEngine.GET("/", static.ServeEmbed("static", EmbedFS)) // 启动健康检查 o.HttpEngine.GET("/healthz", func(c *gin.Context) { c.String(http.StatusOK, "ok") }) // 启动 APIs 服务 diff --git a/api/server/router/static/index.html b/api/server/router/static/index.html new file mode 100644 index 00000000..d03ebc12 --- /dev/null +++ b/api/server/router/static/index.html @@ -0,0 +1,43 @@ + + + + + + 欢迎使用 Pixiu + + + +
+

欢迎使用 Pixiu

+
+ + \ No newline at end of file diff --git a/pkg/static/embedfile.go b/pkg/static/embedfile.go new file mode 100644 index 00000000..85928ded --- /dev/null +++ b/pkg/static/embedfile.go @@ -0,0 +1,67 @@ +/* +* Copyright 2024 Pixiu. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http:*www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ + +package static + +import ( + "embed" + "io/fs" + "net/http" + "strings" + + "github.com/gin-gonic/gin" +) + +type embedFileSystem struct { + http.FileSystem +} + +func (e embedFileSystem) Exists(prefix string, path string) bool { + _, err := e.Open(path) + return err == nil +} + +func EmbedFolder(fsEmbed embed.FS, reqPath string) (ServeFileSystem, error) { + targetPath := strings.TrimSpace(reqPath) + if targetPath == "" { + return embedFileSystem{ + FileSystem: http.FS(fsEmbed), + }, nil + } + + fsys, _ := fs.Sub(fsEmbed, targetPath) + _, err := fsEmbed.Open(targetPath) + if err != nil { + return nil, err + } + + return embedFileSystem{ + FileSystem: http.FS(fsys), + }, nil +} + +func ServeEmbed(reqPath string, fsEmbed embed.FS) gin.HandlerFunc { + embedFS, err := EmbedFolder(fsEmbed, reqPath) + if err != nil { + return func(c *gin.Context) { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "initialization of embed folder failed", + "error": err.Error(), + }) + } + } + return gin.WrapH(http.FileServer(embedFS)) +} diff --git a/pkg/static/servefilesystem.go b/pkg/static/servefilesystem.go new file mode 100644 index 00000000..8f041e3b --- /dev/null +++ b/pkg/static/servefilesystem.go @@ -0,0 +1,52 @@ +/* +Copyright 2024 The Pixiu Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package static + +import ( + "fmt" + "net/http" + + "github.com/gin-gonic/gin" +) + +type ServeFileSystem interface { + http.FileSystem + Exists(prefix string, path string) bool +} + +// Serve returns a middleware handler that serves static files in the given directory. +func Serve(urlPrefix string, fs ServeFileSystem) gin.HandlerFunc { + return ServeCached(urlPrefix, fs, 0) +} + +// ServeCached returns a middleware handler that similar as Serve +// but with the Cache-Control Header set as passed in the cacheAge parameter +func ServeCached(urlPrefix string, fs ServeFileSystem, cacheAge uint) gin.HandlerFunc { + fileserver := http.FileServer(fs) + if urlPrefix != "" { + fileserver = http.StripPrefix(urlPrefix, fileserver) + } + return func(c *gin.Context) { + if fs.Exists(urlPrefix, c.Request.URL.Path) { + if cacheAge != 0 { + c.Writer.Header().Add("Cache-Control", fmt.Sprintf("max-age=%d", cacheAge)) + } + fileserver.ServeHTTP(c.Writer, c.Request) + c.Abort() + } + } +}