webuiServer.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package httpservers
  2. import (
  3. // cors "github.com/OliveTin/OliveTin/internal/cors"
  4. "net/http"
  5. "os"
  6. "path"
  7. log "github.com/sirupsen/logrus"
  8. "github.com/jamesread/golure/pkg/dirs"
  9. config "github.com/OliveTin/OliveTin/internal/config"
  10. )
  11. type webUIServer struct {
  12. cfg *config.Config
  13. webuiDir string
  14. }
  15. var (
  16. customThemeCss []byte
  17. customThemeCssRead = false
  18. )
  19. func NewWebUIServer(cfg *config.Config) *webUIServer {
  20. s := &webUIServer{
  21. cfg: cfg,
  22. }
  23. s.webuiDir = s.findWebuiDir()
  24. s.setupCustomWebuiDir()
  25. return s
  26. }
  27. func (s *webUIServer) handleWebui(w http.ResponseWriter, r *http.Request) {
  28. // dirName := path.Dir(r.URL.Path)
  29. // Mangle requests for any path like /logs or /config to load the webui index.html
  30. if path.Ext(r.URL.Path) == "" && r.URL.Path != "/" {
  31. log.Debugf("Mangling request for %s to /index.html", r.URL.Path)
  32. http.ServeFile(w, r, path.Join(s.webuiDir, "index.html"))
  33. } else {
  34. log.Tracef("Serving webui from %s for %s", s.webuiDir, r.URL.Path)
  35. http.ServeFile(w, r, path.Join(s.webuiDir, r.URL.Path))
  36. // http.StripPrefix(dirName, http.FileServer(http.Dir(s.webuiDir))).ServeHTTP(w, r)
  37. }
  38. }
  39. func (s *webUIServer) findWebuiDir() string {
  40. directoriesToSearch := []string{
  41. s.cfg.WebUIDir,
  42. "../frontend/dist/",
  43. "../webui/",
  44. "../frontend/",
  45. "/usr/share/OliveTin/frontend/",
  46. "/usr/share/OliveTin/webui/",
  47. "/var/www/OliveTin/",
  48. "/var/www/olivetin/",
  49. "/etc/OliveTin/frontend/",
  50. }
  51. dir, err := dirs.GetFirstExistingDirectory("webui", directoriesToSearch)
  52. if err != nil {
  53. log.Warnf("Did not find the webui directory, you will probably get 404 errors.")
  54. return "./webui" // Should not exist
  55. }
  56. log.Infof("Using webui directory: %s", dir)
  57. return dir
  58. }
  59. func (s *webUIServer) findCustomWebuiDir() string {
  60. dir := path.Join(s.cfg.GetDir(), "custom-webui")
  61. return dir
  62. }
  63. func (s *webUIServer) setupCustomWebuiDir() {
  64. dir := s.findCustomWebuiDir()
  65. err := os.MkdirAll(path.Join(dir, "themes/"), 0775)
  66. if err != nil {
  67. log.Warnf("Could not create themes directory: %v", err)
  68. }
  69. }
  70. func shouldReloadThemeCss() bool {
  71. return !customThemeCssRead
  72. }
  73. func loadThemeCssFromFile(filename string) []byte {
  74. _, err := os.Stat(filename)
  75. if err == nil {
  76. css, err := os.ReadFile(filename)
  77. if err != nil {
  78. log.Tracef("Theme CSS file not read: %s", filename)
  79. return nil
  80. }
  81. return css
  82. }
  83. log.Tracef("Theme CSS file not found: %s", filename)
  84. return nil
  85. }
  86. func (s *webUIServer) generateThemeCss(w http.ResponseWriter, r *http.Request) {
  87. themeCssFilename := path.Join(s.findCustomWebuiDir(), "themes", s.cfg.ThemeName, "theme.css")
  88. if shouldReloadThemeCss() || s.cfg.ThemeCacheDisabled {
  89. customThemeCssRead = true
  90. customThemeCss = loadThemeCssFromFile(themeCssFilename)
  91. }
  92. w.Header().Add("Content-Type", "text/css")
  93. _, err := w.Write(customThemeCss)
  94. if err != nil {
  95. log.WithFields(log.Fields{
  96. "error": err,
  97. }).Warnf("Failed to write theme CSS")
  98. }
  99. }
  100. func (s *webUIServer) handleCustomWebui() http.Handler {
  101. return http.StripPrefix("/custom-webui/", http.FileServer(http.Dir(s.findCustomWebuiDir())))
  102. }