2022-09-29 12:37:02 +08:00
|
|
|
package router
|
|
|
|
|
|
|
|
import (
|
|
|
|
"embed"
|
|
|
|
"fmt"
|
|
|
|
"io/fs"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
2022-09-30 16:14:00 +08:00
|
|
|
|
2022-10-24 16:51:05 +08:00
|
|
|
"github.com/answerdev/answer/ui"
|
2022-09-30 16:14:00 +08:00
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/segmentfault/pacman/log"
|
2022-09-29 12:37:02 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
const UIIndexFilePath = "build/index.html"
|
2022-09-30 16:14:00 +08:00
|
|
|
const UIRootFilePath = "build"
|
2022-09-29 12:37:02 +08:00
|
|
|
const UIStaticPath = "build/static"
|
|
|
|
|
|
|
|
// UIRouter is an interface that provides ui static file routers
|
|
|
|
type UIRouter struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewUIRouter creates a new UIRouter instance with the embed resources
|
|
|
|
func NewUIRouter() *UIRouter {
|
|
|
|
return &UIRouter{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// _resource is an interface that provides static file, it's a private interface
|
|
|
|
type _resource struct {
|
|
|
|
fs embed.FS
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open to implement the interface by http.FS required
|
|
|
|
func (r *_resource) Open(name string) (fs.File, error) {
|
|
|
|
name = fmt.Sprintf(UIStaticPath+"/%s", name)
|
|
|
|
log.Debugf("open static path %s", name)
|
|
|
|
return r.fs.Open(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register a new static resource which generated by ui directory
|
|
|
|
func (a *UIRouter) Register(r *gin.Engine) {
|
|
|
|
staticPath := os.Getenv("ANSWER_STATIC_PATH")
|
|
|
|
|
|
|
|
// if ANSWER_STATIC_PATH is set and not empty, ignore embed resource
|
|
|
|
if staticPath != "" {
|
2022-09-29 14:21:49 +08:00
|
|
|
info, err := os.Stat(staticPath)
|
|
|
|
|
2022-09-29 12:37:02 +08:00
|
|
|
if err != nil || !info.IsDir() {
|
|
|
|
log.Error(err)
|
|
|
|
} else {
|
|
|
|
log.Debugf("registering static path %s", staticPath)
|
|
|
|
|
|
|
|
r.LoadHTMLGlob(staticPath + "/*.html")
|
|
|
|
r.Static("/static", staticPath+"/static")
|
|
|
|
r.NoRoute(func(c *gin.Context) {
|
|
|
|
c.HTML(http.StatusOK, "index.html", gin.H{})
|
|
|
|
})
|
|
|
|
|
|
|
|
// return immediately if the static path is set
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// handle the static file by default ui static files
|
|
|
|
r.StaticFS("/static", http.FS(&_resource{
|
|
|
|
fs: ui.Build,
|
|
|
|
}))
|
|
|
|
|
|
|
|
// specify the not router for default routes and redirect
|
|
|
|
r.NoRoute(func(c *gin.Context) {
|
2022-11-14 11:50:00 +08:00
|
|
|
urlPath := c.Request.URL.Path
|
2022-09-30 16:14:00 +08:00
|
|
|
filePath := ""
|
2022-11-14 11:50:00 +08:00
|
|
|
switch urlPath {
|
2022-09-30 16:14:00 +08:00
|
|
|
case "/favicon.ico":
|
|
|
|
c.Header("content-type", "image/vnd.microsoft.icon")
|
2022-11-14 11:50:00 +08:00
|
|
|
filePath = UIRootFilePath + urlPath
|
2022-10-19 14:35:21 +08:00
|
|
|
case "/manifest.json":
|
2022-11-14 11:50:00 +08:00
|
|
|
filePath = UIRootFilePath + urlPath
|
2022-11-10 11:22:07 +08:00
|
|
|
case "/install":
|
2022-11-14 11:50:00 +08:00
|
|
|
// if answer is running by run command user can not access install page.
|
2022-11-10 11:22:07 +08:00
|
|
|
c.Redirect(http.StatusFound, "/")
|
|
|
|
return
|
2022-09-30 16:14:00 +08:00
|
|
|
default:
|
|
|
|
filePath = UIIndexFilePath
|
|
|
|
c.Header("content-type", "text/html;charset=utf-8")
|
|
|
|
}
|
2022-11-14 11:50:00 +08:00
|
|
|
file, err := ui.Build.ReadFile(filePath)
|
2022-09-29 12:37:02 +08:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
c.Status(http.StatusNotFound)
|
|
|
|
return
|
|
|
|
}
|
2022-09-30 16:14:00 +08:00
|
|
|
c.String(http.StatusOK, string(file))
|
2022-09-29 12:37:02 +08:00
|
|
|
})
|
|
|
|
}
|