package main import ( "cmp" "iter" "log/slog" "net/http" "os" "strings" ) var log = slog.New(slog.NewJSONHandler(os.Stdout, nil)) type repoLinkArgs struct { pkgHostname string storageHostname string storageUser string repo string mainBranch string docHostname string } const redirectTemplate = `<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta name="go-import" content="PKG_HOSTNAME/REPO git STORAGE_HOSTNAME/STORAGE_USER/REPO"> <meta name="go-source" content="PKG_HOSTNAME/REPO _ STORAGE_HOSTNAME/STORAGE_USER/REPO/blob/MAIN_BRANCH{/dir} STORAGE_HOSTNAME/STORAGE_USER/REPO/blob/MAIN_BRANCH{/dir}/{file}#L{line}"> <meta http-equiv="refresh" content="0; url=DOC_HOSTNAME/PKG_HOSTNAME/REPO"> </head> <body> Redirecting to docs at <a href="DOC_HOSTNAME/PKG_HOSTNAME/REPO">DOC_HOSTNAME/PKG_HOSTNAME/REPO</a>... </body> </html> ` func mkRepoPage(args repoLinkArgs) string { out := redirectTemplate out = strings.ReplaceAll(out, "PKG_HOSTNAME", args.pkgHostname) out = strings.ReplaceAll(out, "STORAGE_HOSTNAME", args.storageHostname) out = strings.ReplaceAll(out, "STORAGE_USER", args.storageUser) out = strings.ReplaceAll(out, "REPO", args.repo) out = strings.ReplaceAll(out, "MAIN_BRANCH", args.mainBranch) out = strings.ReplaceAll(out, "DOC_HOSTNAME", args.docHostname) return out } var ( pkgHostname = cmp.Or(os.Getenv("GOPKG_PKG_HOSTNAME"), "gopkg.awl.red") storageHostname = cmp.Or(os.Getenv("GOPKG_STORAGE_HOSTNAME"), "https://codeberg.org") storageUser = cmp.Or(os.Getenv("GOPKG_STORAGE_USERNAME"), "neallred") docHostname = cmp.Or(os.Getenv("GOPKG_DOC_HOSTNAME"), "https://godoc.org") defaultMainBranch = cmp.Or(os.Getenv("GOPKG_MAIN_BRANCH"), "master") port = cmp.Or(os.Getenv("GOPKG_PORT"), "8080") addr = cmp.Or(os.Getenv("GOPKG_ADDR"), "0.0.0.0") repoWhitelist = listToSet(strings.SplitSeq(cmp.Or(os.Getenv("GOPKG_REPO_WHITELIST"), ""), ",")) ) func listToSet[T comparable](xs iter.Seq[T]) map[T]struct{} { out := map[T]struct{}{} var zeroVal T for x := range xs { out[x] = struct{}{} } delete(out, zeroVal) return out } func getMainBranch(repo string) string { switch repo { case "phb": return "master" default: return defaultMainBranch } } func main() { http.Handle("GET /{repo}", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { repoValue := r.PathValue("repo") if _, found := repoWhitelist[repoValue]; len(repoWhitelist) > 0 != found { w.WriteHeader(http.StatusNotFound) w.Write([]byte("repo " + repoValue + " not found")) log.Info("404", "repo", repoValue, "remote_addr", r.RemoteAddr, "user_agent", r.UserAgent()) return } log.Info("get repo", "repo", repoValue, "remote_addr", r.RemoteAddr, "user_agent", r.UserAgent()) r.Header.Set("Content-Type", "text/html; charset=utf-8") r.Header.Set("Cache-Control", "public, max-age=300") w.Write([]byte(mkRepoPage(repoLinkArgs{ pkgHostname: pkgHostname, storageHostname: storageHostname, storageUser: storageUser, repo: repoValue, mainBranch: getMainBranch(repoValue), docHostname: docHostname, }))) })) log.Info("listening on", "addr", addr, "port", port) err := http.ListenAndServe(addr+":"+port, nil) if err != nil { log.Info("server end", "err", err) } }