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
import (
"path"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
type Admin struct {
Static string
ProxyAuth string
Username string
Password string
Static string
PathPrefix string
ProxyAuth string
Username string
Password string
}
type Server struct {
@@ -55,6 +58,11 @@ func (Server) Init(cmd *cobra.Command) error {
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")
if err := viper.BindPFlag("admin.proxy_auth", cmd.PersistentFlags().Lookup("admin.proxy_auth")); err != nil {
return err
@@ -81,6 +89,7 @@ func (s *Server) Set() {
s.PProf = viper.GetBool("pprof")
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.Username = viper.GetString("admin.username")
s.Admin.Password = viper.GetString("admin.password")
+60 -33
View File
@@ -2,7 +2,9 @@ package server
import (
"context"
"errors"
"io"
"io/fs"
"net"
"net/http"
"os"
@@ -170,44 +172,69 @@ func New(ApiManager types.ApiManager, roomConfig *config.Room, config *config.Se
return next
}
// cache static file paths
staticFiles := map[string]struct{}{}
if config.Admin.Static != "" {
filepath.Walk(config.Admin.Static,
func(p string, info os.FileInfo, err error) error {
if err != nil {
return err
}
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
// DEPRECATED: admin should not be served from the same path as rooms
if config.Admin.PathPrefix == "/" {
// cache static file paths
staticFiles := map[string]struct{}{}
if config.Admin.Static != "" {
filepath.Walk(config.Admin.Static,
func(p string, info os.FileInfo, err error) error {
if err != nil {
return err
}
staticFiles[path.Clean(p)] = struct{}{}
return nil
})
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
filePath := path.Join(config.Admin.Static, r.URL.Path)
// check if file exists to serve it
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
// serve static files
router.Use(func(next http.Handler) http.Handler {
// if static files are disabled
if config.Admin.Static == "" {
return next
}
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
router.With(protected).Route("/api", ApiManager.Mount)
// check if file exists to serve it
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
router.Handle("/*", proxyHandler)