Files
docs/serve.go
T
zeekay 80b1850210 fix: final audit — go-ethereum refs, graceful shutdown, turbo cache, deploy reliability
Red team fixes:
- Replace 6 remaining go-ethereum references with luxfi/geth
- DAO title: "Welcome" -> "DAO Governance"

CTO fixes:
- serve.go: add graceful shutdown (signal.NotifyContext + srv.Shutdown)
- turbo.json: add out/** to build outputs for proper caching
- deploy.yml: remove continue-on-error (surface deploy failures)
- Delete stale GENESIS_FLOW.md from repo root

452 pages, zero broken links, zero go-ethereum refs
2026-03-25 00:35:44 -07:00

112 lines
2.7 KiB
Go

// Static file server for Lux docs using hanzoai/static.
// Handles Next.js static export clean URLs: tries path, path.html, path/index.html, then 404.
package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"path/filepath"
"syscall"
static "github.com/hanzoai/static"
)
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "3000"
}
root := os.Getenv("ROOT")
if root == "" {
root = "/app"
}
cfg := static.CreateConfig()
cfg.Root = root
cfg.ErrorPage404 = "404.html"
cfg.CacheControl = map[string]string{
".html": "no-cache",
".json": "no-cache",
".js": "public, max-age=31536000, immutable",
".css": "public, max-age=31536000, immutable",
".png": "public, max-age=86400",
".jpg": "public, max-age=86400",
".svg": "public, max-age=86400",
".ico": "public, max-age=86400",
".woff": "public, max-age=31536000, immutable",
".woff2": "public, max-age=31536000, immutable",
"*": "public, max-age=3600",
}
handler, err := static.New(context.Background(), http.NotFoundHandler(), cfg, "docs")
if err != nil {
log.Fatalf("failed to create static handler: %v", err)
}
mux := http.NewServeMux()
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, "ok")
})
// Wrap static handler to try .html extension for clean URLs.
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
urlPath := r.URL.Path
// Root: serve index.html directly (avoid redirect).
if urlPath == "/" {
r.URL.Path = "/index.html"
handler.ServeHTTP(w, r)
return
}
// Has file extension: serve directly.
if filepath.Ext(urlPath) != "" {
handler.ServeHTTP(w, r)
return
}
// Try path.html (Next.js static export generates these).
htmlPath := filepath.Join(root, urlPath+".html")
if _, err := os.Stat(htmlPath); err == nil {
r.URL.Path = urlPath + ".html"
handler.ServeHTTP(w, r)
return
}
// Try path/index.html.
indexPath := filepath.Join(root, urlPath, "index.html")
if _, err := os.Stat(indexPath); err == nil {
r.URL.Path = urlPath + "/index.html"
handler.ServeHTTP(w, r)
return
}
// Fall through to static handler (will serve 404.html).
handler.ServeHTTP(w, r)
})
addr := ":" + port
srv := &http.Server{Addr: addr, Handler: mux}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
go func() {
<-ctx.Done()
log.Println("shutting down...")
srv.Shutdown(context.Background())
}()
log.Printf("serving %s on %s", root, addr)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("server error: %v", err)
}
}