package main import ( "flag" "html/template" "log" "net/http" "net/url" "os" "path" "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"` 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("starting server to listen on %s...", opts.BindAddress) return http.ListenAndServe(opts.BindAddress, handlePackage(&opts)) } var tmpl = template.Must(template.New("package").Parse(`

{{ .Name }}

`)) // A Package represents a Go package's canonical name and its source git // repository. type Package struct { Name string Repo *url.URL } func handlePackage(opts *options) http.HandlerFunc { 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 := &Package{ Name: path.Join(opts.CanonicalPrefix, parts[0]), Repo: &url.URL{ Scheme: "https", Host: "git.burwell.io", Path: parts[0], }, } log.Printf("pkg: %v", pkg) if err := tmpl.Execute(w, pkg); err != nil { log.Printf("could not execute template: %v", err) } } }