package main import ( "flag" "fmt" "io" "net/http" "os" ) type iostreams struct { Err io.Writer Out io.Writer } type Opts struct { ConfigPath string IO iostreams Log func(string) Logf func(string, ...interface{}) } func main() { var configFlag = flag.String("config", "config.yml", "A path to a config file.") flag.Parse() io := iostreams{ Err: os.Stderr, Out: os.Stdout, } opts := Opts{ ConfigPath: *configFlag, IO: io, // TODO use real logger Log: func(s string) { fmt.Fprintln(io.Out, s) }, Logf: func(s string, args ...interface{}) { fmt.Fprintf(io.Out, s, args...) }, } err := _main(opts) if err != nil { fmt.Fprintf(os.Stderr, "failed: %s", err) } } func _main(opts Opts) error { cfg, err := parseConfig(opts.ConfigPath) if err != nil { fmt.Fprintf(os.Stderr, "could not read config file '%s'", opts.ConfigPath) os.Exit(1) } setupAPI(opts, *cfg) // TODO TLS or SSL or something opts.Logf("starting server at %s:%d\n", cfg.Host, cfg.Port) if err := http.ListenAndServe(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port), nil); err != nil { return fmt.Errorf("http server exited with error: %w", err) } return nil } func handler(opts Opts, cfg Config, f http.HandlerFunc) http.HandlerFunc { // TODO make this more real return func(w http.ResponseWriter, req *http.Request) { opts.Log(req.URL.Path) f(w, req) } } func setupAPI(opts Opts, cfg Config) { http.HandleFunc("/instance", handler(opts, cfg, func(w http.ResponseWriter, req *http.Request) { io.WriteString(w, cfg.InstanceName) })) }