add admin path prefix.

This commit is contained in:
Miroslav Šedivý
2023-10-05 21:03:00 +02:00
parent 7da975473f
commit 6e8bcf90e9
2 changed files with 73 additions and 37 deletions
+13 -4
View File
@@ -1,15 +1,18 @@
package config package config
import ( import (
"path"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
type Admin struct { type Admin struct {
Static string Static string
ProxyAuth string PathPrefix string
Username string ProxyAuth string
Password string Username string
Password string
} }
type Server struct { type Server struct {
@@ -55,6 +58,11 @@ func (Server) Init(cmd *cobra.Command) error {
return err return err
} }
cmd.PersistentFlags().String("admin.path_prefix", "/", "path prefix for admin client and API")
if err := viper.BindPFlag("admin.path_prefix", cmd.PersistentFlags().Lookup("admin.path_prefix")); err != nil {
return err
}
cmd.PersistentFlags().String("admin.proxy_auth", "", "require auth: proxy authentication URL, only allow if it returns 200") cmd.PersistentFlags().String("admin.proxy_auth", "", "require auth: proxy authentication URL, only allow if it returns 200")
if err := viper.BindPFlag("admin.proxy_auth", cmd.PersistentFlags().Lookup("admin.proxy_auth")); err != nil { if err := viper.BindPFlag("admin.proxy_auth", cmd.PersistentFlags().Lookup("admin.proxy_auth")); err != nil {
return err return err
@@ -81,6 +89,7 @@ func (s *Server) Set() {
s.PProf = viper.GetBool("pprof") s.PProf = viper.GetBool("pprof")
s.Admin.Static = viper.GetString("admin.static") s.Admin.Static = viper.GetString("admin.static")
s.Admin.PathPrefix = path.Join("/", path.Clean(viper.GetString("admin.path_prefix")))
s.Admin.ProxyAuth = viper.GetString("admin.proxy_auth") s.Admin.ProxyAuth = viper.GetString("admin.proxy_auth")
s.Admin.Username = viper.GetString("admin.username") s.Admin.Username = viper.GetString("admin.username")
s.Admin.Password = viper.GetString("admin.password") s.Admin.Password = viper.GetString("admin.password")
+60 -33
View File
@@ -2,7 +2,9 @@ package server
import ( import (
"context" "context"
"errors"
"io" "io"
"io/fs"
"net" "net"
"net/http" "net/http"
"os" "os"
@@ -170,44 +172,69 @@ func New(ApiManager types.ApiManager, roomConfig *config.Room, config *config.Se
return next return next
} }
// cache static file paths // DEPRECATED: admin should not be served from the same path as rooms
staticFiles := map[string]struct{}{} if config.Admin.PathPrefix == "/" {
if config.Admin.Static != "" { // cache static file paths
filepath.Walk(config.Admin.Static, staticFiles := map[string]struct{}{}
func(p string, info os.FileInfo, err error) error { if config.Admin.Static != "" {
if err != nil { filepath.Walk(config.Admin.Static,
return err func(p string, info os.FileInfo, err error) error {
} if err != nil {
staticFiles[path.Clean(p)] = struct{}{} return err
return nil }
}) staticFiles[path.Clean(p)] = struct{}{}
} return nil
})
// serve static files
router.Use(func(next http.Handler) http.Handler {
// if static files are disabled
if config.Admin.Static == "" {
return next
} }
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // serve static files
filePath := path.Join(config.Admin.Static, r.URL.Path) router.Use(func(next http.Handler) http.Handler {
// if static files are disabled
// check if file exists to serve it if config.Admin.Static == "" {
if _, ok := staticFiles[filePath]; ok { return next
// serve protected assets
protected(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, filePath)
})).ServeHTTP(w, r)
return
} }
next.ServeHTTP(w, r) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
}) filePath := path.Join(config.Admin.Static, r.URL.Path)
})
// serve protected API // check if file exists to serve it
router.With(protected).Route("/api", ApiManager.Mount) if _, ok := staticFiles[filePath]; ok {
// serve protected assets
protected(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, filePath)
})).ServeHTTP(w, r)
return
}
next.ServeHTTP(w, r)
})
})
// serve protected API
router.With(protected).Route("/api", ApiManager.Mount)
} else {
router.With(protected).Route(config.Admin.PathPrefix+"/", func(r chi.Router) {
// serve protected API
r.Route("/api", ApiManager.Mount)
// serve static files
r.Get("/*", func(w http.ResponseWriter, r *http.Request) {
filePath := chi.URLParam(r, "*")
if filePath == "" {
filePath = "index.html"
}
filePath = filepath.Clean(filePath)
filePath = filepath.Join(config.Admin.Static, filePath)
if _, err := os.Stat(filePath); err == nil {
http.ServeFile(w, r, filePath)
} else if errors.Is(err, fs.ErrNotExist) {
http.NotFound(w, r)
} else {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
})
}
// handle all remaining paths with proxy // handle all remaining paths with proxy
router.Handle("/*", proxyHandler) router.Handle("/*", proxyHandler)