static.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package router
  2. import (
  3. "fmt"
  4. "html/template"
  5. "io/fs"
  6. "net/http"
  7. "net/url"
  8. "os"
  9. "path/filepath"
  10. "strings"
  11. "github.com/gin-gonic/gin"
  12. "github.com/labring/aiproxy/core/common/config"
  13. "github.com/labring/aiproxy/core/public"
  14. "github.com/sirupsen/logrus"
  15. )
  16. func SetStaticFileRouter(router *gin.Engine) {
  17. router.SetHTMLTemplate(
  18. template.Must(
  19. template.New("").Funcs(router.FuncMap).ParseFS(public.Templates, "templates/*"),
  20. ),
  21. )
  22. if config.DisableWeb {
  23. router.GET("/", func(ctx *gin.Context) {
  24. ctx.HTML(http.StatusOK, "index.tmpl", gin.H{
  25. "URL": "https://github.com/labring/aiproxy",
  26. "INITIAL_COUNTDOWN": 15,
  27. })
  28. })
  29. return
  30. }
  31. if config.WebPath == "" {
  32. routerFs, ok := public.Public.(fs.ReadDirFS)
  33. if !ok {
  34. panic(fmt.Sprintf("public fs type error: %T, %v", public.Public, public.Public))
  35. }
  36. err := initFSRouter(router, routerFs, ".")
  37. if err != nil {
  38. panic(err)
  39. }
  40. fs := http.FS(public.Public)
  41. router.NoRoute(newIndexNoRouteHandler(fs))
  42. } else {
  43. absPath, err := filepath.Abs(config.WebPath)
  44. if err != nil {
  45. panic(err)
  46. }
  47. logrus.Infof("frontend file path: %s", absPath)
  48. routerFs, ok := os.DirFS(absPath).(fs.ReadDirFS)
  49. if !ok {
  50. panic(fmt.Sprintf("public fs type error: %T, %v", public.Public, public.Public))
  51. }
  52. err = initFSRouter(router, routerFs, ".")
  53. if err != nil {
  54. panic(err)
  55. }
  56. router.NoRoute(newDynamicNoRouteHandler(http.Dir(absPath)))
  57. }
  58. }
  59. func checkNoRouteNotFound(req *http.Request) bool {
  60. if req.Method != http.MethodGet &&
  61. req.Method != http.MethodHead {
  62. return true
  63. }
  64. if strings.HasPrefix(req.URL.Path, "/api") ||
  65. strings.HasPrefix(req.URL.Path, "/mcp") ||
  66. strings.HasPrefix(req.URL.Path, "/v1") {
  67. return true
  68. }
  69. return false
  70. }
  71. func newIndexNoRouteHandler(fs http.FileSystem) func(ctx *gin.Context) {
  72. return func(ctx *gin.Context) {
  73. if checkNoRouteNotFound(ctx.Request) {
  74. http.NotFound(ctx.Writer, ctx.Request)
  75. return
  76. }
  77. ctx.FileFromFS("", fs)
  78. }
  79. }
  80. func newDynamicNoRouteHandler(fs http.FileSystem) func(ctx *gin.Context) {
  81. fileServer := http.StripPrefix("/", http.FileServer(fs))
  82. return func(c *gin.Context) {
  83. if checkNoRouteNotFound(c.Request) {
  84. http.NotFound(c.Writer, c.Request)
  85. return
  86. }
  87. f, err := fs.Open(c.Request.URL.Path)
  88. if err != nil {
  89. c.FileFromFS("", fs)
  90. return
  91. }
  92. f.Close()
  93. fileServer.ServeHTTP(c.Writer, c.Request)
  94. }
  95. }
  96. type staticFileFS interface {
  97. StaticFileFS(relativePath, filepath string, fs http.FileSystem) gin.IRoutes
  98. }
  99. func initFSRouter(e staticFileFS, f fs.ReadDirFS, path string) error {
  100. dirs, err := f.ReadDir(path)
  101. if err != nil {
  102. return err
  103. }
  104. for _, dir := range dirs {
  105. u, err := url.JoinPath(path, dir.Name())
  106. if err != nil {
  107. return err
  108. }
  109. if dir.IsDir() {
  110. err = initFSRouter(e, f, u)
  111. if err != nil {
  112. return err
  113. }
  114. } else {
  115. e.StaticFileFS(u, u, http.FS(f))
  116. }
  117. }
  118. return nil
  119. }