A go version of hepc-serve
This commit is contained in:
104
client/qldbtools/bin/hepc-serve.go
Executable file
104
client/qldbtools/bin/hepc-serve.go
Executable 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()))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user