.html" → that tool's
// embedded HTML. Append ?download to force a save dialog. No auth — tool UI
// only, no data.
func ServeApps(appsSrv *apps.Server, w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet && r.Method != http.MethodHead {
w.Header().Set("Allow", "GET, HEAD")
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
return
}
rest := strings.TrimPrefix(r.URL.Path, AppsVirtualPrefix)
if rest == "" || rest == "index" {
serveAppsIndex(w, r)
return
}
if strings.Contains(rest, "/") {
http.NotFound(w, r)
return
}
body := appBytesForFile(appsSrv, rest)
if body == nil {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
// Conditional-GET-friendly: revalidate each load; bytes change only on a
// binary redeploy. (Index is no-store; it's tiny + generated.)
w.Header().Set("Cache-Control", "max-age=0, must-revalidate")
if r.URL.Query().Get("download") != "" {
w.Header().Set("Content-Disposition", `attachment; filename="`+rest+`"`)
}
if r.Method == http.MethodHead {
return
}
_, _ = w.Write(body)
}
func serveAppsIndex(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Cache-Control", "no-store")
if r.Method == http.MethodHead {
return
}
var b strings.Builder
b.WriteString(``)
b.WriteString(``)
b.WriteString(`ZDDC standalone apps`)
b.WriteString(`ZDDC standalone apps
`)
b.WriteString(`Each tool is a single, self-contained HTML file. Download one and open it from your disk to run it offline against a folder on your own machine (use a Chromium-family browser — it needs the File System Access API). Open runs it here, against the server.
`)
for _, a := range standaloneApps {
b.WriteString(`` + html.EscapeString(a.Name) + `
`)
b.WriteString(`
` + html.EscapeString(a.Desc) + `
`)
b.WriteString(`
Download`)
b.WriteString(`
Open`)
b.WriteString(`
`)
}
b.WriteString(``)
_, _ = w.Write([]byte(b.String()))
}