diff options
Diffstat (limited to 'tools/govanity')
-rw-r--r-- | tools/govanity/go.mod | 2 | ||||
-rw-r--r-- | tools/govanity/go.sum | 3 | ||||
-rw-r--r-- | tools/govanity/main.go | 130 | ||||
-rw-r--r-- | tools/govanity/templates/index.html.tpl | 14 | ||||
-rw-r--r-- | tools/govanity/templates/module.html.tpl | 12 | ||||
-rw-r--r-- | tools/govanity/vanity.yaml | 5 |
6 files changed, 144 insertions, 22 deletions
diff --git a/tools/govanity/go.mod b/tools/govanity/go.mod index 9d1ea60..d37f146 100644 --- a/tools/govanity/go.mod +++ b/tools/govanity/go.mod @@ -1,3 +1,5 @@ module golang.fcuny.net/vanity go 1.16 + +require gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b diff --git a/tools/govanity/go.sum b/tools/govanity/go.sum new file mode 100644 index 0000000..97f8991 --- /dev/null +++ b/tools/govanity/go.sum @@ -0,0 +1,3 @@ +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tools/govanity/main.go b/tools/govanity/main.go index 4afe8d1..dd6d653 100644 --- a/tools/govanity/main.go +++ b/tools/govanity/main.go @@ -1,35 +1,121 @@ -package repo +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 + 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)) } -var vanityTemplate = template.Must(template.New("code").Parse(` -<!DOCTYPE html> -<html> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> - <meta name="go-import" content="src.fcuny.me{{.Name}} git https://github.com/fcuny/{{.Name}}"> - <meta http-equiv="refresh" content="0; url=http://fcuny.me"> - </head> - <body> - </body> -</html> -`)) - -func init() { - http.HandleFunc("/", handleTransactions) +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 handleTransactions(w http.ResponseWriter, r *http.Request) { - repoName := r.URL.Path - p := &repository{Name: repoName} - if err := vanityTemplate.Execute(w, p); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) +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()) } } diff --git a/tools/govanity/templates/index.html.tpl b/tools/govanity/templates/index.html.tpl new file mode 100644 index 0000000..fd8fc56 --- /dev/null +++ b/tools/govanity/templates/index.html.tpl @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <title>golang repo</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> + </head> + <body> + <ul> + {{ range $idx, $m := .Repositories }} + <li>go get <a href="{{ $m.Repo }}">{{ $.BaseUrl }}/{{ $m.Name }}/</a></li> + {{end}} + </ul> + </body> +</html> diff --git a/tools/govanity/templates/module.html.tpl b/tools/govanity/templates/module.html.tpl new file mode 100644 index 0000000..fab3414 --- /dev/null +++ b/tools/govanity/templates/module.html.tpl @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> + <head> + <title>{{.Name}}: golang repo</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> + <meta name="go-import" content="{{.BaseUrl}}/{{.Name}} {{.VCS}} {{.Repo}}"> + <meta name="go-source" content="{{.BaseUrl}}/{{.Name}} _ {{.Repo}}/src{/dir} {{.Repo}}/src{/dir}/{file}/#L{line}"> + </head> + <body> + go get {{.BaseUrl}}/{{.Name}} + </body> +</html> diff --git a/tools/govanity/vanity.yaml b/tools/govanity/vanity.yaml new file mode 100644 index 0000000..a757729 --- /dev/null +++ b/tools/govanity/vanity.yaml @@ -0,0 +1,5 @@ +baseUrl: golang.fcuny.net +vcs: git +repositories: + - name: homelab + repo: https://git.fcuny.net/fcuny/homelab |