Closed jonleopard closed 3 years ago
fs := flag.NewFlagSet("DANKSTATS-API", flag.ExitOnError)
var (
listenAddr = fs.String("listen-addr", "localhost:4000", "listen address")
_ = fs.String("config", "", "config file")
)
ff.Parse(fs, os.Args[1:],
ff.WithEnvVarPrefix("DANKSTATS-API"),
ff.WithConfigFileFlag("config"),
ff.WithConfigFileParser(ff.PlainParser),
)
So ff.WithConfigFileFlag("config")
tells ff to use the value of the -config
flag as the filename to read, and ff.WithConfigFileParser(ff.PlainParser)
tells ff to parse that file with the PlainParser. You probably want to use the ffyaml.Parser instead, there.
Also, I'm not sure that env var prefixes can contain -
— you probably want DANKSTATS_API
.
Does that work?
You’re right, I had to change it to DANKSTATS_API
. I think I’ll skip env vars and just go with setting with flags or a file. What would be the cleanest way to give my handler methods access to these keys? My handlers are already hanging off of the server, so I guess I could add an additional field for the config?
type Server struct {
mux *chi.Mux
log *zap.SugaredLogger
server *http.Server
config ???
}
...
srv := &Server{
mux: mux,
config: ???
server: &http.Server{
Addr: *listenAddr,
ReadTimeout: 5 * time.Second,
ReadHeaderTimeout: 5 * time.Second,
WriteTimeout: 5 * time.Second,
IdleTimeout: 5 * time.Second,
},
}
...
// HandleTopGames responds with the top twitch games
func (s *Server) HandleTopGames(w http.ResponseWriter, r *http.Request) {
client, err := helix.NewClient(&helix.Options{
ClientID: *clientID, <--- value read from flag || file
AppAccessToken: *appAccessToken,
})
if err != nil {
panic(err)
}
resp, err := client.GetTopGames(&helix.TopGamesParams{
First: 20,
})
if err != nil {
panic(err)
}
json.NewEncoder(w).Encode(resp)
}
Thanks again for your input on this!
Components don't take the whole app config, they take the specific bits of it which are relevant to them, by default just as individual parameters.
Glad this helped!
No bugs or any issues to report here, just a usage question :-)
After reading a couple of your blog posts, I’m sold on your stance on flags being the best way to configure your app. I’m working on a personal project that requires some API credentials. Using flags for simple parameters like a port is very straight forward. For running in a dev environment, I think it would make sense to have API secrets be kept in a file. I’ve created a .yaml file in my root,
config.dev.yaml
, and would likeff
to read this file and inject it where necessary (for example, see theHandleTopGames
method below). I will have an examplesample.dev.yaml
file where developers can fill in their own API credentials.Where I’m lost is how to actually get
ff
to read the config file. How does it know the path (or do I need to specify where it is?). Suffice it to say I’m still pretty new to go, and I’m trying to learn some best practices. Apologies in advanced if my question is trivial! Any input is greatly appreciated :-)Cheers!