dist.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package controller
  2. import (
  3. "bytes"
  4. "embed"
  5. htmlpkg "html"
  6. "net/http"
  7. "strings"
  8. "time"
  9. "github.com/gin-gonic/gin"
  10. "github.com/mhsanaei/3x-ui/v3/config"
  11. "github.com/mhsanaei/3x-ui/v3/logger"
  12. "github.com/mhsanaei/3x-ui/v3/web/session"
  13. )
  14. var distFS embed.FS
  15. func SetDistFS(fs embed.FS) {
  16. distFS = fs
  17. }
  18. var distPageBuildTime = time.Now()
  19. func serveDistPage(c *gin.Context, name string) {
  20. body, err := distFS.ReadFile("dist/" + name)
  21. if err != nil {
  22. c.String(http.StatusInternalServerError, "missing embedded page: %s", name)
  23. return
  24. }
  25. basePath := c.GetString("base_path")
  26. if basePath == "" {
  27. basePath = "/"
  28. }
  29. if basePath != "/" {
  30. body = bytes.ReplaceAll(body, []byte(`src="/assets/`), []byte(`src="`+basePath+`assets/`))
  31. body = bytes.ReplaceAll(body, []byte(`href="/assets/`), []byte(`href="`+basePath+`assets/`))
  32. }
  33. jsEscape := strings.NewReplacer(
  34. `\`, `\\`,
  35. `"`, `\"`,
  36. "\n", `\n`,
  37. "\r", `\r`,
  38. "<", `<`,
  39. ">", `>`,
  40. "&", `&`,
  41. )
  42. escapedBase := jsEscape.Replace(basePath)
  43. escapedVer := jsEscape.Replace(config.GetVersion())
  44. csrfToken, err := session.EnsureCSRFToken(c)
  45. if err != nil {
  46. logger.Warning("Unable to mint CSRF token for", name+":", err)
  47. csrfToken = ""
  48. }
  49. csrfMeta := []byte(`<meta name="csrf-token" content="` + htmlpkg.EscapeString(csrfToken) + `">`)
  50. inject := []byte(`<script>window.X_UI_BASE_PATH="` + escapedBase +
  51. `";window.X_UI_CUR_VER="` + escapedVer + `";</script>`)
  52. inject = append(inject, csrfMeta...)
  53. inject = append(inject, []byte(`</head>`)...)
  54. out := bytes.Replace(body, []byte("</head>"), inject, 1)
  55. c.Header("Cache-Control", "no-cache, no-store, must-revalidate")
  56. c.Header("Pragma", "no-cache")
  57. c.Header("Expires", "0")
  58. c.Header("Last-Modified", distPageBuildTime.UTC().Format(http.TimeFormat))
  59. c.Data(http.StatusOK, "text/html; charset=utf-8", out)
  60. }