-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Support embed api-ui resources - The ui-path arg will be applied if provided. Also applied to api-ui resource files
- Loading branch information
1 parent
004e475
commit eacc474
Showing
18 changed files
with
447 additions
and
223 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package config | ||
|
||
import ( | ||
"github.com/rancher/steve/pkg/debug" | ||
stevecli "github.com/rancher/steve/pkg/server/cli" | ||
) | ||
|
||
var ( | ||
Steve stevecli.Config | ||
Debug debug.Config | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package ui | ||
|
||
import "github.com/rancher/apiserver/pkg/writer" | ||
|
||
type APIUI struct { | ||
offline StringSetting | ||
release BoolSetting | ||
embed bool | ||
} | ||
|
||
func apiUI(opt *Options) APIUI { | ||
var rtn = APIUI{ | ||
offline: opt.Offline, | ||
release: opt.ReleaseSetting, | ||
embed: true, | ||
} | ||
if rtn.offline == nil { | ||
rtn.offline = StaticSetting("dynamic") | ||
} | ||
if rtn.release == nil { | ||
rtn.release = StaticSetting(false) | ||
} | ||
for _, file := range []string{ | ||
"ui/api-ui/ui.min.css", | ||
"ui/api-ui/ui.min.js", | ||
} { | ||
if _, err := staticContent.Open(file); err != nil { | ||
rtn.embed = false | ||
break | ||
} | ||
} | ||
return rtn | ||
} | ||
|
||
func (a APIUI) content(name string) writer.StringGetter { | ||
return func() (rtn string) { | ||
switch a.offline() { | ||
case "dynamic": | ||
if !a.release() && !a.embed { | ||
return "" | ||
} | ||
case "false": | ||
return "" | ||
} | ||
return name | ||
} | ||
} | ||
|
||
func (a APIUI) CSS() writer.StringGetter { | ||
return a.content("/api-ui/ui.min.css") | ||
} | ||
|
||
func (a APIUI) JS() writer.StringGetter { | ||
return a.content("/api-ui/ui.min.js") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package content | ||
|
||
import ( | ||
"io/fs" | ||
"net/http" | ||
) | ||
|
||
type fsFunc func(name string) (fs.File, error) | ||
|
||
func (f fsFunc) Open(name string) (fs.File, error) { | ||
return f(name) | ||
} | ||
|
||
type fsContent interface { | ||
ToFileServer(basePaths ...string) http.Handler | ||
Open(name string) (fs.File, error) | ||
} | ||
|
||
type Handler interface { | ||
ServeAssets(middleware func(http.Handler) http.Handler, hext http.Handler) http.Handler | ||
ServeFaviconDashboard() http.Handler | ||
GetIndex() ([]byte, error) | ||
Refresh() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package content | ||
|
||
import ( | ||
"bytes" | ||
"crypto/tls" | ||
"errors" | ||
"io" | ||
"net/http" | ||
"sync" | ||
) | ||
|
||
const ( | ||
defaultIndex = "https://releases.rancher.com/dashboard/latest/index.html" | ||
) | ||
|
||
func NewExternal(getIndex func() string) Handler { | ||
return &externalIndexHandler{ | ||
getIndexFunc: getIndex, | ||
} | ||
} | ||
|
||
var ( | ||
insecureClient = &http.Client{ | ||
Transport: &http.Transport{ | ||
Proxy: http.ProxyFromEnvironment, | ||
TLSClientConfig: &tls.Config{ | ||
InsecureSkipVerify: true, | ||
}, | ||
}, | ||
} | ||
_ Handler = &externalIndexHandler{} | ||
) | ||
|
||
type externalIndexHandler struct { | ||
sync.RWMutex | ||
getIndexFunc func() string | ||
current string | ||
downloadSuccess *bool | ||
} | ||
|
||
func (u *externalIndexHandler) ServeAssets(_ func(http.Handler) http.Handler, next http.Handler) http.Handler { | ||
return next | ||
} | ||
|
||
func (u *externalIndexHandler) ServeFaviconDashboard() http.Handler { | ||
return http.NotFoundHandler() | ||
} | ||
|
||
func (u *externalIndexHandler) GetIndex() ([]byte, error) { | ||
if u.canDownload() { | ||
var buffer bytes.Buffer | ||
if err := serveIndex(&buffer, u.current); err != nil { | ||
return nil, err | ||
} | ||
return buffer.Bytes(), nil | ||
} | ||
return nil, errors.New("external index is not available") | ||
} | ||
|
||
func serveIndex(resp io.Writer, url string) error { | ||
r, err := insecureClient.Get(url) | ||
if err != nil { | ||
return err | ||
} | ||
defer r.Body.Close() | ||
|
||
_, err = io.Copy(resp, r.Body) | ||
return err | ||
} | ||
|
||
func (u *externalIndexHandler) canDownload() bool { | ||
u.RLock() | ||
rtn := u.downloadSuccess | ||
u.RUnlock() | ||
if rtn != nil { | ||
return *rtn | ||
} | ||
|
||
return u.refresh() | ||
} | ||
|
||
func (u *externalIndexHandler) refresh() bool { | ||
u.Lock() | ||
defer u.RUnlock() | ||
|
||
u.current = u.getIndexFunc() | ||
if u.current == "" { | ||
u.current = defaultIndex | ||
} | ||
t := serveIndex(io.Discard, u.current) == nil | ||
u.downloadSuccess = &t | ||
return t | ||
} | ||
|
||
func (u *externalIndexHandler) Refresh() { | ||
_ = u.refresh() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package content | ||
|
||
import ( | ||
"io" | ||
"net/http" | ||
"path/filepath" | ||
"sync" | ||
) | ||
|
||
var _ Handler = &handler{} | ||
|
||
func newFS(content fsContent) Handler { | ||
return &handler{ | ||
content: content, | ||
cacheFS: &sync.Map{}, | ||
} | ||
} | ||
|
||
type handler struct { | ||
content fsContent | ||
cacheFS *sync.Map | ||
} | ||
|
||
func (h *handler) pathExist(path string) bool { | ||
_, err := h.content.Open(path) | ||
return err == nil | ||
} | ||
|
||
func (h *handler) serveContent(basePaths ...string) http.Handler { | ||
key := filepath.Join(basePaths...) | ||
if rtn, ok := h.cacheFS.Load(key); ok { | ||
return rtn.(http.Handler) | ||
} | ||
|
||
rtn := h.content.ToFileServer(basePaths...) | ||
h.cacheFS.Store(key, rtn) | ||
return rtn | ||
} | ||
|
||
func (h *handler) Refresh() { | ||
h.cacheFS.Range(func(key, _ any) bool { | ||
h.cacheFS.Delete(key) | ||
return true | ||
}) | ||
} | ||
|
||
func (h *handler) ServeAssets(middleware func(http.Handler) http.Handler, next http.Handler) http.Handler { | ||
assets := middleware(h.serveContent()) | ||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
if h.pathExist(r.URL.Path) { | ||
assets.ServeHTTP(w, r) | ||
} else { | ||
next.ServeHTTP(w, r) | ||
} | ||
}) | ||
} | ||
|
||
func (h *handler) ServeFaviconDashboard() http.Handler { | ||
return h.serveContent("dashboard") | ||
|
||
} | ||
|
||
func (h *handler) GetIndex() ([]byte, error) { | ||
path := filepath.Join("dashboard", "index.html") | ||
f, err := h.content.Open(path) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer f.Close() | ||
return io.ReadAll(f) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package content | ||
|
||
import ( | ||
"embed" | ||
"io/fs" | ||
"net/http" | ||
"path/filepath" | ||
) | ||
|
||
func NewEmbedded(staticContent embed.FS, prefix string) Handler { | ||
return newFS(&embedFS{ | ||
pathPrefix: prefix, | ||
staticContent: staticContent, | ||
}) | ||
} | ||
|
||
var _ fsContent = &embedFS{} | ||
|
||
type embedFS struct { | ||
pathPrefix string | ||
staticContent embed.FS | ||
} | ||
|
||
// Open implements fsContent. | ||
func (e *embedFS) Open(name string) (fs.File, error) { | ||
return e.staticContent.Open(joinEmbedFilepath(e.pathPrefix, name)) | ||
} | ||
|
||
// ToFileServer implements fsContent. | ||
func (e *embedFS) ToFileServer(basePaths ...string) http.Handler { | ||
handler := fsFunc(func(name string) (fs.File, error) { | ||
assetPath := joinEmbedFilepath(joinEmbedFilepath(basePaths...), name) | ||
return e.Open(assetPath) | ||
}) | ||
|
||
return http.FileServer(http.FS(handler)) | ||
} | ||
|
||
func (e *embedFS) Refresh() error { return nil } | ||
|
||
func joinEmbedFilepath(paths ...string) string { | ||
return filepath.ToSlash(filepath.Join(paths...)) | ||
} |
Oops, something went wrong.