mirror of
https://github.com/cnrancher/kube-explorer.git
synced 2025-04-28 11:14:44 +00:00
138 lines
3.4 KiB
Go
138 lines
3.4 KiB
Go
package ui
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/cnrancher/kube-explorer/internal/ui/content"
|
|
"github.com/rancher/apiserver/pkg/middleware"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type StringSetting func() string
|
|
type BoolSetting func() bool
|
|
|
|
func StaticSetting[T any](input T) func() T {
|
|
return func() T {
|
|
return input
|
|
}
|
|
}
|
|
|
|
type Handler struct {
|
|
contentHandlers map[string]content.Handler
|
|
pathSetting func() string
|
|
indexSetting func() string
|
|
releaseSetting func() bool
|
|
offlineSetting func() string
|
|
middleware func(http.Handler) http.Handler
|
|
indexMiddleware func(http.Handler) http.Handler
|
|
}
|
|
|
|
type Options struct {
|
|
// The location on disk of the UI files
|
|
Path StringSetting
|
|
// The HTTP URL of the index file to download
|
|
Index StringSetting
|
|
// Whether or not to run the UI offline, should return true/false/dynamic/embed
|
|
Offline StringSetting
|
|
// Whether or not is it release, if true UI will run offline if set to dynamic
|
|
ReleaseSetting BoolSetting
|
|
}
|
|
|
|
func NewUIHandler(opts *Options) *Handler {
|
|
if opts == nil {
|
|
opts = &Options{}
|
|
}
|
|
|
|
h := &Handler{
|
|
contentHandlers: make(map[string]content.Handler),
|
|
indexSetting: opts.Index,
|
|
offlineSetting: opts.Offline,
|
|
pathSetting: opts.Path,
|
|
releaseSetting: opts.ReleaseSetting,
|
|
middleware: middleware.Chain{
|
|
middleware.Gzip,
|
|
middleware.FrameOptions,
|
|
middleware.CacheMiddleware("json", "js", "css"),
|
|
}.Handler,
|
|
indexMiddleware: middleware.Chain{
|
|
middleware.Gzip,
|
|
middleware.NoCache,
|
|
middleware.FrameOptions,
|
|
middleware.ContentType,
|
|
}.Handler,
|
|
}
|
|
|
|
if h.indexSetting == nil {
|
|
h.indexSetting = StaticSetting("")
|
|
}
|
|
|
|
if h.offlineSetting == nil {
|
|
h.offlineSetting = StaticSetting("dynamic")
|
|
}
|
|
|
|
if h.pathSetting == nil {
|
|
h.pathSetting = StaticSetting("")
|
|
}
|
|
|
|
if h.releaseSetting == nil {
|
|
h.releaseSetting = StaticSetting(false)
|
|
}
|
|
|
|
h.contentHandlers["embed"] = content.NewEmbedded(staticContent, "ui")
|
|
h.contentHandlers["false"] = content.NewExternal(h.indexSetting)
|
|
h.contentHandlers["true"] = content.NewFilepath(h.pathSetting)
|
|
|
|
return h
|
|
}
|
|
|
|
func (h *Handler) content() content.Handler {
|
|
offline := h.offlineSetting()
|
|
if handler, ok := h.contentHandlers[offline]; ok {
|
|
return handler
|
|
}
|
|
embedHandler := h.contentHandlers["embed"]
|
|
filepathHandler := h.contentHandlers["true"]
|
|
externalHandler := h.contentHandlers["false"]
|
|
// default to dynamic
|
|
switch {
|
|
case h.pathSetting() != "":
|
|
if _, err := filepathHandler.GetIndex(); err == nil {
|
|
return filepathHandler
|
|
}
|
|
fallthrough
|
|
case h.releaseSetting():
|
|
// release must use embed first
|
|
return embedHandler
|
|
default:
|
|
// try embed
|
|
if _, err := embedHandler.GetIndex(); err == nil {
|
|
return embedHandler
|
|
}
|
|
return externalHandler
|
|
}
|
|
}
|
|
|
|
func (h *Handler) ServeAssets(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
h.content().ServeAssets(h.middleware, next).ServeHTTP(w, r)
|
|
})
|
|
}
|
|
|
|
func (h *Handler) ServeFaviconDashboard() http.Handler {
|
|
return h.middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
h.content().ServeFaviconDashboard().ServeHTTP(w, r)
|
|
}))
|
|
}
|
|
|
|
func (h *Handler) IndexFile() http.Handler {
|
|
return h.indexMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
rtn, err := h.content().GetIndex()
|
|
if err != nil {
|
|
logrus.Warnf("failed to serve index with error %v", err)
|
|
http.NotFoundHandler().ServeHTTP(w, r)
|
|
return
|
|
}
|
|
_, _ = w.Write(rtn)
|
|
}))
|
|
}
|