package main import ( "embed" "io" "net/http" "strconv" ) // Cross-compiled companion binaries served as downloads from the wiki footer // flyout when no local companion is detected. The Makefile produces these // before invoking `go build .`; missing files will fail the build at compile // time via the embed directive below. // //go:embed companion/datascape-companion-windows-amd64.exe //go:embed companion/datascape-companion-linux-amd64 var companionBinaries embed.FS func init() { http.HandleFunc("/companion/download/windows", serveCompanionBinary( "companion/datascape-companion-windows-amd64.exe", "datascape-companion.exe", )) http.HandleFunc("/companion/download/linux", serveCompanionBinary( "companion/datascape-companion-linux-amd64", "datascape-companion", )) } func serveCompanionBinary(embedPath, downloadName string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { w.Header().Set("Allow", http.MethodGet) http.Error(w, "method not allowed", http.StatusMethodNotAllowed) return } f, err := companionBinaries.Open(embedPath) if err != nil { http.Error(w, "companion binary not available", http.StatusNotFound) return } defer f.Close() info, err := f.Stat() if err != nil { http.Error(w, "companion binary not available", http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Disposition", `attachment; filename="`+downloadName+`"`) w.Header().Set("Content-Length", strconv.FormatInt(info.Size(), 10)) _, _ = io.Copy(w, f) } }