From cb8c0bfad3aad3611d3db669b2de1f6911fe01e2 Mon Sep 17 00:00:00 2001 From: Yar Kravtsov Date: Sun, 24 Sep 2023 12:16:52 +0300 Subject: [PATCH] refactor config --- cmd/main.go | 8 ++++---- config/config.go | 46 +++++++++++++++++++++++++--------------------- go.mod | 8 +------- go.sum | 17 ----------------- logger/logger.go | 15 +++++---------- 5 files changed, 35 insertions(+), 59 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 3b6c4b6..3fb528f 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -30,7 +30,7 @@ func main() { flag.Parse() // Fetch the API Gateway's configuration using the utility function from the internal package. - err, config := config.GetConfig() + cfg, err := config.GetConfig() if err != nil { // Log and exit if there's an error loading the configuration. log.Fatal("Error loading configuration:", err) @@ -38,7 +38,7 @@ func main() { // Initialize the router with the provided configuration. This router handles // requests based on the vhost, endpoint, and backend service configurations. - r := router.NewRouter(config) + r := router.NewRouter(cfg) // Create a new server and configure it. srv := &http.Server{ @@ -69,10 +69,10 @@ func main() { // Log the start of the server and the port on which it is running. log.Infof("Server is ready to handle requests at %s", serverAddr) - if config.UseTLS { + if cfg.UseTLS { srv.TLSConfig = &tls.Config{ GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) { - for vhostName, vhost := range config.Vhosts { + for vhostName, vhost := range cfg.Vhosts { if vhost.TLS != nil { // Using wildcard pattern matching to determine the appropriate certificate. match, err := filepath.Match(vhostName, info.ServerName) diff --git a/config/config.go b/config/config.go index ec38178..31fe2ed 100644 --- a/config/config.go +++ b/config/config.go @@ -81,35 +81,39 @@ type Config struct { // GetConfig reads the API Gateway's configuration from a JSON file and returns it. // It handles any issues with reading or parsing the configuration file. -func GetConfig() (error, *Config) { +func GetConfig() (*Config, error) { content, err := os.ReadFile("config.json") if err != nil { - return fmt.Errorf("error reading config.json: %w", err), nil + return nil, fmt.Errorf("error reading config.json: %w", err) } - var config Config - err = json.Unmarshal(content, &config) - if err != nil { - return fmt.Errorf("error parsing config.json: %w", err), nil + config := new(Config) // Use new() to get a pointer directly, prevent local-to-heap migration. + if err = json.Unmarshal(content, config); err != nil { + return nil, fmt.Errorf("error parsing config.json: %w", err) } - // Check the TLS configurations for all vhosts - vhostsWithSSL := 0 - for _, vhost := range config.Vhosts { - if vhost.TLS != nil { - vhostsWithSSL++ - } - } + anyVhostWithSSL, allVhostsWithSSL := check(config) - // If there are any vhosts with TLS configured, then all vhosts should have TLS configured. - if vhostsWithSSL > 0 && vhostsWithSSL != len(config.Vhosts) { - return fmt.Errorf("configuration error: either all vhosts should have TLS configured, or none should"), nil + // If there's any vhost with TLS configured but not all of them have, then it's a config error. + if anyVhostWithSSL && !allVhostsWithSSL { + return nil, fmt.Errorf("configuration error: either all vhosts should have TLS configured, or none should") } - // If there are vhosts with TLS configured, then the API Gateway should use TLS. - if vhostsWithSSL > 0 { - config.UseTLS = true - } + config.UseTLS = anyVhostWithSSL + return config, nil +} + +func check(config *Config) (bool, bool) { + // Check if any vhost has TLS configured + anyVhostWithSSL := false + allVhostsWithSSL := true - return err, &config + for _, vhost := range config.Vhosts { + if vhost.TLS != nil { + anyVhostWithSSL = true + } else { + allVhostsWithSSL = false + } + } + return anyVhostWithSSL, allVhostsWithSSL } diff --git a/go.mod b/go.mod index 878001a..382d560 100644 --- a/go.mod +++ b/go.mod @@ -7,15 +7,9 @@ require ( github.com/go-chi/cors v1.2.1 github.com/gorilla/websocket v1.5.0 github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.8.4 ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/pretty v0.3.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.8.1 // indirect + github.com/stretchr/testify v1.8.4 // indirect golang.org/x/sys v0.11.0 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 0e2d0f4..60c280d 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -8,20 +7,8 @@ github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -32,10 +19,6 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/logger/logger.go b/logger/logger.go index 8ba768b..76fbfbc 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -10,10 +10,8 @@ import ( // L is a logger instance, utilized throughout the application to output structured logs. var L *logrus.Logger -// JsonLogger is a middleware that wraps around HTTP handlers to provide logging capabilities. -// For every incoming request, it logs key details like the method, URL, remote address, -// response status, bytes written, duration taken, and a unique request ID. The logs -// are written in a structured JSON format to ensure easy parsing and visualization. +const logMessage = "HTTP request" // Define a constant for the log message + func JsonLogger(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Capture the start time to compute the duration of the request. @@ -23,9 +21,8 @@ func JsonLogger(next http.Handler) http.Handler { ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor) next.ServeHTTP(ww, r) - // Set the log format to JSON and log the request details. - logrus.SetFormatter(&logrus.JSONFormatter{}) - logrus.WithFields(logrus.Fields{ + // Log the request details. + L.WithFields(logrus.Fields{ "method": r.Method, "url": r.URL.String(), "remote_addr": r.RemoteAddr, @@ -33,7 +30,7 @@ func JsonLogger(next http.Handler) http.Handler { "bytes": ww.BytesWritten(), "duration": time.Since(start).Seconds() * 1000, "request_id": r.Context().Value(middleware.RequestIDKey), - }).Info("HTTP request") + }).Info(logMessage) }) } @@ -41,8 +38,6 @@ func GetLogger() *logrus.Logger { return L } -// init initializes the logger instance L and sets its format to JSON -// so that all logs produced are structured accordingly. func init() { L = logrus.New() L.SetFormatter(&logrus.JSONFormatter{})