Add config file parsing/dumping

chubin/logging
Igor Chubin 2 years ago
parent 2328b29bfe
commit 5d86d36b7e

@ -7,3 +7,6 @@ github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

@ -1,5 +1,14 @@
package config
import (
"log"
"os"
"gopkg.in/yaml.v3"
"github.com/chubin/wttr.in/internal/util"
)
// Config of the program.
type Config struct {
Cache
@ -12,13 +21,13 @@ type Config struct {
type Logging struct {
// AccessLog path.
AccessLog string
AccessLog string `yaml:"accessLog,omitempty"`
// ErrorsLog path.
ErrorsLog string
ErrorsLog string `yaml:"errorsLog,omitempty"`
// Interval between access log flushes, in seconds.
Interval int
Interval int `yaml:"interval,omitempty"`
}
// Server configuration.
@ -26,36 +35,36 @@ type Server struct {
// PortHTTP is port where HTTP server must listen.
// If 0, HTTP is disabled.
PortHTTP int
PortHTTP int `yaml:"portHTTP,omitempty"`
// PortHTTP is port where the HTTPS server must listen.
// If 0, HTTPS is disabled.
PortHTTPS int
PortHTTPS int `yaml:"portHTTPS,omitempty"`
// TLSCertFile contains path to cert file for TLS Server.
TLSCertFile string
TLSCertFile string `yaml:"tlsCertFile,omitempty"`
// TLSCertFile contains path to key file for TLS Server.
TLSKeyFile string
TLSKeyFile string `yaml:"tlsKeyFile,omitempty"`
}
// Uplink configuration.
type Uplink struct {
// Address contains address of the uplink server in form IP:PORT.
Address string
Address string `yaml:"address,omitempty"`
// Timeout for upstream queries.
Timeout int
Timeout int `yaml:"timeout,omitempty"`
// PrefetchInterval contains time (in milliseconds) indicating,
// how long the prefetch procedure should take.
PrefetchInterval int
PrefetchInterval int `yaml:"prefetchInterval,omitempty"`
}
// Cache configuration.
type Cache struct {
// Size of the main cache.
Size int
Size int `yaml:"size,omitempty"`
}
// Default contains the default configuration.
@ -83,5 +92,32 @@ func Default() *Config {
}
}
// Conf contains the current configuration
var Conf = Default()
// Load config from file.
func Load(filename string) (*Config, error) {
var (
config Config
data []byte
err error
)
data, err = os.ReadFile(filename)
if err != nil {
return nil, err
}
err = util.YamlUnmarshalStrict(data, &config)
if err != nil {
return nil, err
}
return &config, nil
}
func (c *Config) Dump() []byte {
data, err := yaml.Marshal(c)
if err != nil {
// should never happen.
log.Fatalln("config.Dump():", err)
}
return data
}

@ -44,7 +44,7 @@ func serveHTTP(mux *http.ServeMux, port int, logFile io.Writer, errs chan<- erro
errs <- srv.ListenAndServe()
}
func serveHTTPS(mux *http.ServeMux, port int, logFile io.Writer, errs chan<- error) {
func serveHTTPS(mux *http.ServeMux, port int, certFile, keyFile string, logFile io.Writer, errs chan<- error) {
tlsConfig := &tls.Config{
// CipherSuites: []uint16{
@ -63,18 +63,16 @@ func serveHTTPS(mux *http.ServeMux, port int, logFile io.Writer, errs chan<- err
TLSConfig: tlsConfig,
Handler: mux,
}
errs <- srv.ListenAndServeTLS(config.Conf.Server.TLSCertFile, config.Conf.Server.TLSKeyFile)
errs <- srv.ListenAndServeTLS(certFile, keyFile)
}
func main() {
func serve(conf *config.Config) error {
var (
// mux is main HTTP/HTTP requests multiplexer.
mux *http.ServeMux = http.NewServeMux()
// logger is optimized requests logger.
logger *logging.RequestLogger = logging.NewRequestLogger(
config.Conf.Logging.AccessLog,
time.Duration(config.Conf.Logging.Interval)*time.Second)
logger *logging.RequestLogger
rp *processor.RequestProcessor
@ -84,8 +82,18 @@ func main() {
// numberOfServers started. If 0, exit.
numberOfServers int
errorsLog *logging.LogSuppressor = logging.NewLogSuppressor(
config.Conf.Logging.ErrorsLog,
errorsLog *logging.LogSuppressor
err error
)
// logger is optimized requests logger.
logger = logging.NewRequestLogger(
conf.Logging.AccessLog,
time.Duration(conf.Logging.Interval)*time.Second)
errorsLog = logging.NewLogSuppressor(
conf.Logging.ErrorsLog,
[]string{
"error reading preface from client",
"TLS handshake error from",
@ -93,10 +101,7 @@ func main() {
logLineStart,
)
err error
)
rp, err = processor.NewRequestProcessor(config.Conf)
rp, err = processor.NewRequestProcessor(conf)
if err != nil {
log.Fatalln("log processor initialization:", err)
}
@ -129,17 +134,45 @@ func main() {
w.Write(response.Body)
})
if config.Conf.Server.PortHTTP != 0 {
go serveHTTP(mux, config.Conf.Server.PortHTTP, errorsLog, errs)
if conf.Server.PortHTTP != 0 {
go serveHTTP(mux, conf.Server.PortHTTP, errorsLog, errs)
numberOfServers++
}
if config.Conf.Server.PortHTTPS != 0 {
go serveHTTPS(mux, config.Conf.Server.PortHTTPS, errorsLog, errs)
if conf.Server.PortHTTPS != 0 {
go serveHTTPS(mux, conf.Server.PortHTTPS, conf.Server.TLSCertFile, conf.Server.TLSKeyFile, errorsLog, errs)
numberOfServers++
}
if numberOfServers == 0 {
log.Println("no servers configured; exiting")
return errors.New("no servers configured")
}
return <-errs // block until one of the servers writes an error
}
func main() {
var (
conf *config.Config
err error
)
ctx := kong.Parse(&cli)
if cli.ConfigFile != "" {
conf, err = config.Load(cli.ConfigFile)
if err != nil {
log.Fatalf("reading config from %s: %s\n", cli.ConfigFile, err)
}
} else {
conf = config.Default()
}
if cli.ConfigDump {
fmt.Print(string(conf.Dump()))
}
if cli.ConfigCheck || cli.ConfigDump {
return
}
log.Fatal(<-errs) // block until one of the servers writes an error
err = serve(conf)
ctx.FatalIfErrorf(err)
}

Loading…
Cancel
Save