about summary refs log tree commit diff
path: root/tools/govanity/main.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tools/govanity/main.go121
1 files changed, 121 insertions, 0 deletions
diff --git a/tools/govanity/main.go b/tools/govanity/main.go
new file mode 100644
index 0000000..dd6d653
--- /dev/null
+++ b/tools/govanity/main.go
@@ -0,0 +1,121 @@
+package main
+
+import (
+	"bytes"
+	"embed"
+	"flag"
+	"html/template"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"strings"
+
+	"gopkg.in/yaml.v3"
+)
+
+//go:embed templates
+var tpls embed.FS
+
+type repository struct {
+	Name string `yaml:"name"`
+	Repo string `yaml:"repo"`
+}
+
+type config struct {
+	BaseUrl      string       `yaml:"baseUrl"`
+	VCS          string       `yaml:"vcs"`
+	Repositories []repository `yaml:"repositories"`
+}
+
+type moduleTmpl struct {
+	Name    string
+	Repo    string
+	VCS     string
+	BaseUrl string
+}
+
+func main() {
+	flag.Parse()
+	buf, err := ioutil.ReadFile("vanity.yaml")
+	if err != nil {
+		log.Fatalf("failed to read the configuration: %+v", err)
+	}
+
+	cfg := &config{}
+	err = yaml.Unmarshal(buf, cfg)
+	if err != nil {
+		log.Fatalf("failed to parse the YAML configuration: %+v", err)
+	}
+
+	http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(200)
+		w.Write([]byte("ok"))
+	})
+
+	http.HandleFunc("/", goGet(cfg))
+
+	log.Printf("starting web server on :8080")
+	log.Fatal(http.ListenAndServe(":8080", nil))
+}
+
+func goGet(cfg *config) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		if r.Method != http.MethodGet {
+			status := http.StatusMethodNotAllowed
+			http.Error(w, http.StatusText(status), status)
+			return
+		}
+
+		if r.FormValue("go-get") == "1" {
+			pathParts := strings.Split(r.URL.Path, "/")
+			for _, m := range cfg.Repositories {
+				if pathParts[1] == m.Name {
+					goGetModule(w, r, m, cfg)
+					return
+				}
+			}
+			status := http.StatusNotFound
+			http.Error(w, http.StatusText(status), status)
+			return
+		}
+		browserURL(w, r, cfg)
+	}
+}
+
+func goGetModule(w http.ResponseWriter, r *http.Request, m repository, cfg *config) {
+	tmpl, err := template.ParseFS(tpls, "templates/module.html.tpl")
+	if err != nil {
+		log.Fatal(err)
+	}
+	mod := moduleTmpl{
+		VCS:     cfg.VCS,
+		BaseUrl: cfg.BaseUrl,
+		Name:    m.Name,
+		Repo:    m.Repo,
+	}
+	var buf bytes.Buffer
+	if err := tmpl.Execute(&buf, mod); err != nil {
+		log.Printf("error: %+v", err)
+		status := http.StatusInternalServerError
+		http.Error(w, http.StatusText(status), status)
+	} else {
+		w.Header().Set("Cache-Control", "no-store")
+		w.Write(buf.Bytes())
+	}
+}
+
+func browserURL(w http.ResponseWriter, r *http.Request, cfg *config) {
+	tmpl, err := template.ParseFS(tpls, "templates/index.html.tpl")
+	if err != nil {
+		log.Fatal(err)
+	}
+	var buf bytes.Buffer
+	if err := tmpl.Execute(&buf, cfg); err != nil {
+		log.Printf("error: %+v", err)
+		status := http.StatusInternalServerError
+		http.Error(w, http.StatusText(status), status)
+	} else {
+		w.Header().Set("Cache-Control", "no-store")
+		w.Write(buf.Bytes())
+	}
+}