A go version of hepc-serve

This commit is contained in:
Michael Hohn
2024-11-27 22:56:47 -08:00
parent 95d2638546
commit 3db629e2ca

View File

@@ -0,0 +1,104 @@
/*
dependencies
go get -u golang.org/x/exp/slog
on-the-fly
go run bin/hepc-serve.go --codeql-db-dir db-collection-py-1
compiled
cd ~/work-gh/mrva/mrvacommander/client/qldbtools/
go build -o ./bin/hepc-serve.bin ./bin/hepc-serve.go
test
curl http://127.0.0.1:8080/api/v1/latest_results/codeql-all -o foo
curl $(head -1 foo | jq -r ".result_url" |sed 's|hepc|127.0.0.1:8080/db|g;') -o foo.zip
*/
package main
import (
"flag"
"fmt"
"net/http"
"os"
"path/filepath"
"golang.org/x/exp/slog"
)
var dbDir string
func serveFile(w http.ResponseWriter, r *http.Request) {
fullPath := r.URL.Path[len("/db/"):]
resolvedPath, err := filepath.EvalSymlinks(fullPath)
if err != nil {
slog.Warn("failed to resolve symlink", slog.String("fullPath", fullPath),
slog.String("error", err.Error()))
http.Error(w, "File not found", http.StatusNotFound)
return
}
if fileInfo, err := os.Stat(resolvedPath); err != nil || fileInfo.IsDir() {
slog.Warn("file not found or is a directory", slog.String("resolvedPath", resolvedPath))
http.Error(w, "File not found", http.StatusNotFound)
return
}
slog.Info("serving file", slog.String("resolvedPath", resolvedPath))
http.ServeFile(w, r, resolvedPath)
}
func serveMetadata(w http.ResponseWriter, r *http.Request) {
metadataPath := filepath.Join(dbDir, "metadata.json")
if fileInfo, err := os.Stat(metadataPath); err != nil || fileInfo.IsDir() {
slog.Warn("metadata.json not found", slog.String("metadataPath", metadataPath))
http.Error(w, "metadata.json not found", http.StatusNotFound)
return
}
slog.Info("serving metadata.json", slog.String("metadataPath", metadataPath))
http.ServeFile(w, r, metadataPath)
}
func logMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
slog.Info("incoming request", slog.String("method", r.Method), slog.String("url", r.URL.Path))
next.ServeHTTP(w, r)
})
}
func main() {
var host string
var port int
flag.StringVar(&dbDir, "codeql-db-dir", "", "Directory containing CodeQL database files (required)")
flag.StringVar(&host, "host", "127.0.0.1", "Host address for the HTTP server")
flag.IntVar(&port, "port", 8080, "Port for the HTTP server")
flag.Parse()
if dbDir == "" {
slog.Error("missing required flag", slog.String("flag", "--codeql-db-dir"))
os.Exit(1)
}
if _, err := os.Stat(dbDir); os.IsNotExist(err) {
slog.Error("invalid directory", slog.String("dbDir", dbDir))
os.Exit(1)
}
slog.Info("starting server", slog.String("host", host), slog.Int("port", port), slog.String("dbDir", dbDir))
mux := http.NewServeMux()
mux.HandleFunc("/db/", serveFile)
mux.HandleFunc("/index", serveMetadata)
mux.HandleFunc("/api/v1/latest_results/codeql-all", serveMetadata)
loggedHandler := logMiddleware(mux)
addr := fmt.Sprintf("%s:%d", host, port)
slog.Info("server listening", slog.String("address", addr))
if err := http.ListenAndServe(addr, loggedHandler); err != nil {
slog.Error("server error", slog.String("error", err.Error()))
}
}