Embed web assets into the Go binary
Serve /static from embedded assets when no static path override is configured, add static route coverage, and update Docker/docs to reflect embedded-by-default behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -17,9 +17,6 @@ RUN apk add --no-cache ca-certificates docker-cli
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=builder /out/webterm /usr/local/bin/webterm
|
COPY --from=builder /out/webterm /usr/local/bin/webterm
|
||||||
COPY go/webterm/static /app/static
|
|
||||||
|
|
||||||
ENV WEBTERM_STATIC_PATH=/app/static
|
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
|
|||||||
@@ -120,5 +120,5 @@ docker build -t webterm .
|
|||||||
docker run -v /var/run/docker.sock:/var/run/docker.sock -p 8080:8080 webterm --docker-watch
|
docker run -v /var/run/docker.sock:/var/run/docker.sock -p 8080:8080 webterm --docker-watch
|
||||||
```
|
```
|
||||||
|
|
||||||
The image sets `WEBTERM_STATIC_PATH=/app/static` and serves assets from `go/webterm/static`.
|
Web assets are embedded in the Go binary by default (you can still override with `WEBTERM_STATIC_PATH`).
|
||||||
The Dockerfile uses a minimal Alpine runtime stage and only installs `ca-certificates` plus `docker-cli`.
|
The Dockerfile uses a minimal Alpine runtime stage and only installs `ca-certificates` plus `docker-cli`.
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ The server resolves static files from:
|
|||||||
|
|
||||||
1. `WEBTERM_STATIC_PATH` (if set)
|
1. `WEBTERM_STATIC_PATH` (if set)
|
||||||
2. local repository-relative fallbacks rooted at `go/webterm/static`
|
2. local repository-relative fallbacks rooted at `go/webterm/static`
|
||||||
|
3. embedded assets bundled into the Go binary
|
||||||
|
|
||||||
## Docker integration
|
## Docker integration
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package webterm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed static static/* static/js/* static/icons/*
|
||||||
|
var embeddedStaticAssets embed.FS
|
||||||
|
|
||||||
|
func embeddedStaticFS() (http.FileSystem, bool) {
|
||||||
|
sub, err := fs.Sub(embeddedStaticAssets, "static")
|
||||||
|
if err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return http.FS(sub), true
|
||||||
|
}
|
||||||
@@ -1466,6 +1466,8 @@ func (s *LocalServer) Handler() http.Handler {
|
|||||||
mux.HandleFunc("/", s.handleRoot)
|
mux.HandleFunc("/", s.handleRoot)
|
||||||
if strings.TrimSpace(s.staticPath) != "" {
|
if strings.TrimSpace(s.staticPath) != "" {
|
||||||
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(s.staticPath))))
|
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(s.staticPath))))
|
||||||
|
} else if staticFS, ok := embeddedStaticFS(); ok {
|
||||||
|
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(staticFS)))
|
||||||
}
|
}
|
||||||
return s.loggingMiddleware(s.gzipMiddleware(mux))
|
return s.loggingMiddleware(s.gzipMiddleware(mux))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,6 +221,15 @@ func TestRootTerminalPageAndSparklineValidation(t *testing.T) {
|
|||||||
t.Fatalf("unexpected root page: %q", text)
|
t.Fatalf("unexpected root page: %q", text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
respStatic, err := http.Get(httpServer.URL + "/static/manifest.json")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("static request error = %v", err)
|
||||||
|
}
|
||||||
|
_ = respStatic.Body.Close()
|
||||||
|
if respStatic.StatusCode != http.StatusOK {
|
||||||
|
t.Fatalf("expected 200 for static manifest, got %d", respStatic.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
resp2, err := http.Get(httpServer.URL + "/cpu-sparkline.svg")
|
resp2, err := http.Get(httpServer.URL + "/cpu-sparkline.svg")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("sparkline request error = %v", err)
|
t.Fatalf("sparkline request error = %v", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user