package main import ( "flag" "html/template" "log" "net/http" "os" "strings" "time" "github.com/BurntSushi/toml" ) func main() { if err := run(); err != nil { log.Fatal(err) } } type duration struct { time.Duration } func (d *duration) UnmarshalText(text []byte) error { var err error d.Duration, err = time.ParseDuration(string(text)) return err } type options struct { BindAddress string `toml:"bind_address"` CacheExpiry duration `toml:"cache_expiry"` UpstreamTimeout duration `toml:"upstream_timeout"` SourcehutUsername string `toml:"srht_username"` SourcehutToken string `toml:"srht_token"` GithubUsername string `toml:"github_username"` GithubToken string `toml:"github_token"` CanonicalPrefix string `toml:"canonical_prefix"` } func run() error { cfgPath := flag.String("c", "", "path to configuration file") flag.Parse() if cfgPath == nil || *cfgPath == "" { flag.Usage() os.Exit(1) } var opts options if _, err := toml.DecodeFile(*cfgPath, &opts); err != nil { return err } log.Printf("caches expire after %s", opts.CacheExpiry.Duration) log.Printf("upstream reqs time out after %s", opts.UpstreamTimeout.Duration) cache := &PackageCache{ CanonicalPrefix: opts.CanonicalPrefix, ExpireAfter: opts.CacheExpiry.Duration, UpstreamTimeout: opts.UpstreamTimeout.Duration, Logger: log.New(os.Stdout, "", log.LstdFlags), Hosts: []RepoHost{ Sourcehut{Username: opts.SourcehutUsername, Token: opts.SourcehutToken}, Github{Username: opts.GithubUsername, Token: opts.GithubToken}, }, } handler := handlePackage(cache) log.Printf("starting server to listen on %s...", opts.BindAddress) return http.ListenAndServe(opts.BindAddress, handler) } func handlePackage(pkgs *PackageCache) http.HandlerFunc { tmpl, err := template.New("package").Parse(`

{{ .Name }}

`) if err != nil { return nil } return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(http.StatusText(http.StatusBadRequest))) return } parts := strings.SplitN(r.URL.Path[1:], "/", 2) pkg, ok := pkgs.Get(r.Context(), parts[0]) if !ok { w.WriteHeader(http.StatusNotFound) w.Write([]byte(http.StatusText(http.StatusNotFound))) return } log.Printf("pkg: %v", pkg) tmpl.Execute(w, pkg) } }