From c76cf5bd41f15abd692699e0e1e18d247e57863b Mon Sep 17 00:00:00 2001 From: Jonas Kaninda Date: Sun, 17 Nov 2024 05:28:27 +0100 Subject: [PATCH] refactor: refactoring of code to meet all golangci-lint requirements --- .golangci.yml | 44 ++++++ cmd/config/check.go | 3 +- cmd/config/config.go | 3 +- cmd/config/init.go | 5 +- internal/checkConfig.go | 2 +- internal/config.go | 2 +- internal/cors_type.go | 6 +- internal/gateway_type.go | 2 +- internal/handler.go | 6 +- internal/helpers.go | 2 +- internal/metrics/prometheus.go | 5 +- internal/middleware_type.go | 2 +- internal/middlewares/middleware.go | 3 +- internal/middlewares/rate-limit.go | 4 +- internal/middlewares/types.go | 13 +- internal/proxy.go | 4 +- internal/redis.go | 11 +- internal/route.go | 232 +++++++++++++++-------------- internal/route_type.go | 6 +- internal/server.go | 13 +- internal/types.go | 13 +- pkg/logger/logger.go | 6 +- pkg/logger/var.go | 20 +++ util/helpers.go | 5 +- 24 files changed, 236 insertions(+), 176 deletions(-) create mode 100644 .golangci.yml create mode 100644 pkg/logger/var.go diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..67baf9e --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,44 @@ +run: + timeout: 5m + allow-parallel-runners: true + +issues: + # don't skip warning about doc comments + # don't exclude the default set of lint + exclude-use-default: false + # restore some of the defaults + # (fill in the rest as needed) + exclude-rules: + - path: "internal/*" + linters: + - dupl + - lll +linters: + disable-all: true + enable: + - dupl + - errcheck + - copyloopvar + - ginkgolinter + - goconst + - gocyclo + - gofmt + #- goimports + - gosimple + - govet + - ineffassign + - lll + - misspell + - nakedret + - prealloc + - revive + - staticcheck + - typecheck + - unconvert + - unparam + - unused + +linters-settings: + revive: + rules: + - name: comment-spacings diff --git a/cmd/config/check.go b/cmd/config/check.go index ce6c762..5073a1e 100644 --- a/cmd/config/check.go +++ b/cmd/config/check.go @@ -19,9 +19,10 @@ package config import ( "fmt" + "os" + pkg "github.com/jkaninda/goma-gateway/internal" "github.com/spf13/cobra" - "os" ) var CheckConfigCmd = &cobra.Command{ diff --git a/cmd/config/config.go b/cmd/config/config.go index 7ea675f..ddc27df 100644 --- a/cmd/config/config.go +++ b/cmd/config/config.go @@ -18,8 +18,9 @@ package config import ( "fmt" - "github.com/spf13/cobra" "os" + + "github.com/spf13/cobra" ) var Cmd = &cobra.Command{ diff --git a/cmd/config/init.go b/cmd/config/init.go index 789b211..04d39a4 100644 --- a/cmd/config/init.go +++ b/cmd/config/init.go @@ -17,9 +17,10 @@ limitations under the License. */ import ( "fmt" - "github.com/jkaninda/goma-gateway/internal" - "github.com/spf13/cobra" "os" + + pkg "github.com/jkaninda/goma-gateway/internal" + "github.com/spf13/cobra" ) var InitConfigCmd = &cobra.Command{ diff --git a/internal/checkConfig.go b/internal/checkConfig.go index 2b54aab..3ca5bd6 100644 --- a/internal/checkConfig.go +++ b/internal/checkConfig.go @@ -52,7 +52,7 @@ func CheckConfig(fileName string) error { } } - //Check middlewares + // Check middlewares for index, mid := range c.Middlewares { if util.HasWhitespace(mid.Name) { fmt.Printf("Warning: Middleware contains whitespace: %s | index: [%d], please remove whitespace characters\n", mid.Name, index) diff --git a/internal/config.go b/internal/config.go index 3909014..6fdcbe3 100644 --- a/internal/config.go +++ b/internal/config.go @@ -76,7 +76,7 @@ func (GatewayServer) Config(configFile string, ctx context.Context) (*GatewaySer } logger.Info("Generating new configuration file...") - //check if config directory does exist + // check if config directory does exist if !util.FolderExists(ConfigDir) { err := os.MkdirAll(ConfigDir, os.ModePerm) if err != nil { diff --git a/internal/cors_type.go b/internal/cors_type.go index 717cf43..b2c9d85 100644 --- a/internal/cors_type.go +++ b/internal/cors_type.go @@ -19,16 +19,16 @@ package pkg type Cors struct { // Cors Allowed origins, - //e.g: + // e.g: // // - http://localhost:80 // // - https://example.com Origins []string `yaml:"origins"` // - //e.g: + // e.g: // - //Access-Control-Allow-Origin: '*' + // Access-Control-Allow-Origin: '*' // // Access-Control-Allow-Methods: 'GET, POST, PUT, DELETE, OPTIONS' // diff --git a/internal/gateway_type.go b/internal/gateway_type.go index 23467c5..7118f4e 100644 --- a/internal/gateway_type.go +++ b/internal/gateway_type.go @@ -42,7 +42,7 @@ type Gateway struct { DisableHealthCheckStatus bool `yaml:"disableHealthCheckStatus"` // DisableRouteHealthCheckError allows enabling and disabling backend healthcheck errors DisableRouteHealthCheckError bool `yaml:"disableRouteHealthCheckError"` - //Disable allows enabling and disabling displaying routes on start + // Disable allows enabling and disabling displaying routes on start DisableDisplayRouteOnStart bool `yaml:"disableDisplayRouteOnStart"` // DisableKeepAlive allows enabling and disabling KeepALive server DisableKeepAlive bool `yaml:"disableKeepAlive"` diff --git a/internal/handler.go b/internal/handler.go index 5d53df1..1016aa0 100644 --- a/internal/handler.go +++ b/internal/handler.go @@ -32,11 +32,11 @@ func CORSHandler(cors Cors) mux.MiddlewareFunc { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Set CORS headers from the cors config - //Update Cors Headers + // Update Cors Headers for k, v := range cors.Headers { w.Header().Set(k, v) } - //Update Origin Cors Headers + // Update Origin Cors Headers if allowedOrigin(cors.Origins, r.Header.Get("Origin")) { // Handle preflight requests (OPTIONS) if r.Method == "OPTIONS" { @@ -90,7 +90,7 @@ func (heathRoute HealthCheckRoute) HealthCheckHandler(w http.ResponseWriter, r * } wg.Wait() // Wait for all requests to complete response := HealthCheckResponse{ - Status: "healthy", //Goma proxy + Status: "healthy", // Goma proxy Routes: routes, // Routes health check } w.Header().Set("Content-Type", "application/json") diff --git a/internal/helpers.go b/internal/helpers.go index fb0ec4b..992b0f7 100644 --- a/internal/helpers.go +++ b/internal/helpers.go @@ -76,7 +76,7 @@ func (oauth *OauthRulerMiddleware) getUserInfo(token *oauth2.Token) (UserInfo, e defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { - + return } }(resp.Body) diff --git a/internal/metrics/prometheus.go b/internal/metrics/prometheus.go index e888ba3..65ec31e 100644 --- a/internal/metrics/prometheus.go +++ b/internal/metrics/prometheus.go @@ -18,11 +18,12 @@ package metrics import ( + "net/http" + "strconv" + "github.com/gorilla/mux" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "net/http" - "strconv" ) type PrometheusRoute struct { diff --git a/internal/middleware_type.go b/internal/middleware_type.go index 1bd9426..2087773 100644 --- a/internal/middleware_type.go +++ b/internal/middleware_type.go @@ -19,7 +19,7 @@ package pkg // Middleware defined the route middlewares type Middleware struct { - //Path contains the name of middlewares and must be unique + // Path contains the name of middlewares and must be unique Name string `yaml:"name"` // Type contains authentication types // diff --git a/internal/middlewares/middleware.go b/internal/middlewares/middleware.go index ebc3ddd..f8fc1b8 100644 --- a/internal/middlewares/middleware.go +++ b/internal/middlewares/middleware.go @@ -33,7 +33,7 @@ func (jwtAuth JwtAuth) AuthMiddleware(next http.Handler) http.Handler { if r.Header.Get(header) == "" { logger.Error("Proxy error, missing %s header", header) w.Header().Set("Content-Type", "application/json") - //check allowed origin + // check allowed origin if allowedOrigin(jwtAuth.Origins, r.Header.Get("Origin")) { w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) } @@ -42,7 +42,6 @@ func (jwtAuth JwtAuth) AuthMiddleware(next http.Handler) http.Handler { } } - //token := r.Header.Get("Authorization") authURL, err := url.Parse(jwtAuth.AuthURL) if err != nil { logger.Error("Error parsing auth URL: %v", err) diff --git a/internal/middlewares/rate-limit.go b/internal/middlewares/rate-limit.go index 3a8bfe3..3a1ac09 100644 --- a/internal/middlewares/rate-limit.go +++ b/internal/middlewares/rate-limit.go @@ -29,8 +29,6 @@ func (rl *TokenRateLimiter) RateLimitMiddleware() mux.MiddlewareFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if !rl.Allow() { logger.Error("Too many requests from IP: %s %s %s", getRealIP(r), r.URL, r.UserAgent()) - //RespondWithError(w, http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized), basicAuth.ErrorInterceptor) - // Rate limit exceeded, return a 429 Too Many Requests response w.WriteHeader(http.StatusTooManyRequests) _, err := w.Write([]byte(fmt.Sprintf("%d Too many requests, API requests limit exceeded. Please try again later", http.StatusTooManyRequests))) @@ -75,7 +73,7 @@ func (rl *RateLimiter) RateLimitMiddleware() mux.MiddlewareFunc { if client.RequestCount > rl.requests { logger.Error("Too many requests from IP: %s %s %s", clientIP, r.URL, r.UserAgent()) - //Update Origin Cors Headers + // Update Origin Cors Headers if allowedOrigin(rl.origins, r.Header.Get("Origin")) { w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) } diff --git a/internal/middlewares/types.go b/internal/middlewares/types.go index 5bcfb7c..49c9112 100644 --- a/internal/middlewares/types.go +++ b/internal/middlewares/types.go @@ -26,13 +26,12 @@ import ( // RateLimiter defines requests limit properties. type RateLimiter struct { - requests int - id string - window time.Duration - clientMap map[string]*Client - mu sync.Mutex - origins []string - //hosts []string + requests int + id string + window time.Duration + clientMap map[string]*Client + mu sync.Mutex + origins []string redisBased bool } diff --git a/internal/proxy.go b/internal/proxy.go index 217a6a4..dac8b20 100644 --- a/internal/proxy.go +++ b/internal/proxy.go @@ -44,7 +44,7 @@ func (proxyRoute ProxyRoute) ProxyHandler() http.HandlerFunc { } } // Set CORS headers from the cors config - //Update Cors Headers + // Update Cors Headers for k, v := range proxyRoute.cors.Headers { w.Header().Set(k, v) } @@ -87,7 +87,7 @@ func (proxyRoute ProxyRoute) ProxyHandler() http.HandlerFunc { InsecureSkipVerify: proxyRoute.insecureSkipVerify, }, } - w.Header().Set("Proxied-By", gatewayName) //Set Server name + w.Header().Set("Proxied-By", gatewayName) // Set Server name w.Header().Del("Server") // Remove the Server header // Custom error handler for proxy errors proxy.ErrorHandler = ProxyErrorHandler diff --git a/internal/redis.go b/internal/redis.go index 8802e28..7e5d027 100644 --- a/internal/redis.go +++ b/internal/redis.go @@ -22,13 +22,12 @@ import ( "github.com/jkaninda/goma-gateway/pkg/logger" ) -func (gatewayServer GatewayServer) initRedis() error { - if gatewayServer.gateway.Redis.Addr == "" { - return nil +func (gatewayServer GatewayServer) initRedis() { + if len(gatewayServer.gateway.Redis.Addr) != 0 { + logger.Info("Initializing Redis...") + middlewares.InitRedis(gatewayServer.gateway.Redis.Addr, gatewayServer.gateway.Redis.Password) } - logger.Info("Initializing Redis...") - middlewares.InitRedis(gatewayServer.gateway.Redis.Addr, gatewayServer.gateway.Redis.Password) - return nil + } func (gatewayServer GatewayServer) closeRedis() { diff --git a/internal/route.go b/internal/route.go index 419214e..4bb75bf 100644 --- a/internal/route.go +++ b/internal/route.go @@ -32,7 +32,7 @@ func init() { _ = prometheus.Register(metrics.HttpDuration) } -// Initialize the routes +// Initialize initializes the routes func (gatewayServer GatewayServer) Initialize() *mux.Router { gateway := gatewayServer.gateway m := gatewayServer.middlewares @@ -40,8 +40,9 @@ func (gatewayServer GatewayServer) Initialize() *mux.Router { if len(gateway.Redis.Addr) != 0 { redisBased = true } - //Routes background healthcheck + // Routes background healthcheck routesHealthCheck(gateway.Routes) + r := mux.NewRouter() heath := HealthCheckRoute{ DisableRouteHealthCheckError: gateway.DisableRouteHealthCheckError, @@ -68,7 +69,7 @@ func (gatewayServer GatewayServer) Initialize() *mux.Router { if gateway.RateLimit != 0 { // Add rate limit middlewares to all routes, if defined rateLimit := middlewares.RateLimit{ - Id: "global_rate", //Generate a unique ID for routes + Id: "global_rate", // Generate a unique ID for routes Requests: gateway.RateLimit, Window: time.Minute, // requests per minute Origins: gateway.Cors.Origins, @@ -80,16 +81,17 @@ func (gatewayServer GatewayServer) Initialize() *mux.Router { r.Use(limiter.RateLimitMiddleware()) } for rIndex, route := range gateway.Routes { - if route.Path != "" { - if route.Destination == "" && len(route.Backends) == 0 { + if len(route.Path) != 0 { + // Checks if route destination and backend are empty + if len(route.Destination) == 0 && len(route.Backends) == 0 { logger.Fatal("Route %s : destination or backends should not be empty", route.Name) } - // Apply middlewares to route - for _, mid := range route.Middlewares { - if mid != "" { + // Apply middlewares to the route + for _, middleware := range route.Middlewares { + if middleware != "" { // Get Access middlewares if it does exist - accessMiddleware, err := getMiddleware([]string{mid}, m) + accessMiddleware, err := getMiddleware([]string{middleware}, m) if err != nil { logger.Error("Error: %v", err.Error()) } else { @@ -105,114 +107,12 @@ func (gatewayServer GatewayServer) Initialize() *mux.Router { } // Get route authentication middlewares if it does exist - rMiddleware, err := getMiddleware([]string{mid}, m) + routeMiddleware, err := getMiddleware([]string{middleware}, m) if err != nil { - //Error: middlewares not found + // Error: middlewares not found logger.Error("Error: %v", err.Error()) } else { - for _, midPath := range rMiddleware.Paths { - proxyRoute := ProxyRoute{ - path: route.Path, - rewrite: route.Rewrite, - destination: route.Destination, - backends: route.Backends, - disableHostFording: route.DisableHostFording, - methods: route.Methods, - cors: route.Cors, - insecureSkipVerify: route.InsecureSkipVerify, - } - secureRouter := r.PathPrefix(util.ParseRoutePath(route.Path, midPath)).Subrouter() - //callBackRouter := r.PathPrefix(util.ParseRoutePath(route.Path, "/callback")).Subrouter() - //Check Authentication middlewares - switch rMiddleware.Type { - case BasicAuth: - basicAuth, err := getBasicAuthMiddleware(rMiddleware.Rule) - if err != nil { - logger.Error("Error: %s", err.Error()) - } else { - amw := middlewares.AuthBasic{ - Username: basicAuth.Username, - Password: basicAuth.Password, - Headers: nil, - Params: nil, - } - // Apply JWT authentication middlewares - secureRouter.Use(amw.AuthMiddleware) - secureRouter.Use(CORSHandler(route.Cors)) - secureRouter.PathPrefix("/").Handler(proxyRoute.ProxyHandler()) // Proxy handler - secureRouter.PathPrefix("").Handler(proxyRoute.ProxyHandler()) // Proxy handler - } - case JWTAuth: - jwt, err := getJWTMiddleware(rMiddleware.Rule) - if err != nil { - logger.Error("Error: %s", err.Error()) - } else { - amw := middlewares.JwtAuth{ - AuthURL: jwt.URL, - RequiredHeaders: jwt.RequiredHeaders, - Headers: jwt.Headers, - Params: jwt.Params, - Origins: gateway.Cors.Origins, - } - // Apply JWT authentication middlewares - secureRouter.Use(amw.AuthMiddleware) - secureRouter.Use(CORSHandler(route.Cors)) - secureRouter.PathPrefix("/").Handler(proxyRoute.ProxyHandler()) // Proxy handler - secureRouter.PathPrefix("").Handler(proxyRoute.ProxyHandler()) // Proxy handler - - } - case OAuth, "openid": - oauth, err := oAuthMiddleware(rMiddleware.Rule) - if err != nil { - logger.Error("Error: %s", err.Error()) - } else { - redirectURL := "/callback" + route.Path - if oauth.RedirectURL != "" { - redirectURL = oauth.RedirectURL - } - amw := middlewares.Oauth{ - ClientID: oauth.ClientID, - ClientSecret: oauth.ClientSecret, - RedirectURL: redirectURL, - Scopes: oauth.Scopes, - Endpoint: middlewares.OauthEndpoint{ - AuthURL: oauth.Endpoint.AuthURL, - TokenURL: oauth.Endpoint.TokenURL, - UserInfoURL: oauth.Endpoint.UserInfoURL, - }, - State: oauth.State, - Origins: gateway.Cors.Origins, - JWTSecret: oauth.JWTSecret, - Provider: oauth.Provider, - } - oauthRuler := oauthRulerMiddleware(amw) - // Check if a cookie path is defined - if oauthRuler.CookiePath == "" { - oauthRuler.CookiePath = route.Path - } - // Check if a RedirectPath is defined - if oauthRuler.RedirectPath == "" { - oauthRuler.RedirectPath = util.ParseRoutePath(route.Path, midPath) - } - if oauthRuler.Provider == "" { - oauthRuler.Provider = "custom" - } - secureRouter.Use(amw.AuthMiddleware) - secureRouter.Use(CORSHandler(route.Cors)) - secureRouter.PathPrefix("/").Handler(proxyRoute.ProxyHandler()) // Proxy handler - secureRouter.PathPrefix("").Handler(proxyRoute.ProxyHandler()) // Proxy handler - // Callback route - r.HandleFunc(util.UrlParsePath(redirectURL), oauthRuler.callbackHandler).Methods("GET") - } - default: - if !doesExist(rMiddleware.Type) { - logger.Error("Unknown middlewares type %s", rMiddleware.Type) - } - - } - - } - + attachAuthMiddlewares(route, routeMiddleware, gateway, r) } } else { logger.Error("Error, middlewares path is empty") @@ -300,3 +200,107 @@ func (gatewayServer GatewayServer) Initialize() *mux.Router { return r } + +func attachAuthMiddlewares(route Route, routeMiddleware Middleware, gateway Gateway, r *mux.Router) { + for _, middlewarePath := range routeMiddleware.Paths { + proxyRoute := ProxyRoute{ + path: route.Path, + rewrite: route.Rewrite, + destination: route.Destination, + backends: route.Backends, + disableHostFording: route.DisableHostFording, + methods: route.Methods, + cors: route.Cors, + insecureSkipVerify: route.InsecureSkipVerify, + } + secureRouter := r.PathPrefix(util.ParseRoutePath(route.Path, middlewarePath)).Subrouter() + // Check Authentication middleware types + switch routeMiddleware.Type { + case BasicAuth: + basicAuth, err := getBasicAuthMiddleware(routeMiddleware.Rule) + if err != nil { + logger.Error("Error: %s", err.Error()) + } else { + authBasic := middlewares.AuthBasic{ + Username: basicAuth.Username, + Password: basicAuth.Password, + Headers: nil, + Params: nil, + } + // Apply JWT authentication middlewares + secureRouter.Use(authBasic.AuthMiddleware) + secureRouter.Use(CORSHandler(route.Cors)) + secureRouter.PathPrefix("/").Handler(proxyRoute.ProxyHandler()) // Proxy handler + secureRouter.PathPrefix("").Handler(proxyRoute.ProxyHandler()) // Proxy handler + } + case JWTAuth: + jwt, err := getJWTMiddleware(routeMiddleware.Rule) + if err != nil { + logger.Error("Error: %s", err.Error()) + } else { + jwtAuth := middlewares.JwtAuth{ + AuthURL: jwt.URL, + RequiredHeaders: jwt.RequiredHeaders, + Headers: jwt.Headers, + Params: jwt.Params, + Origins: gateway.Cors.Origins, + } + // Apply JWT authentication middlewares + secureRouter.Use(jwtAuth.AuthMiddleware) + secureRouter.Use(CORSHandler(route.Cors)) + secureRouter.PathPrefix("/").Handler(proxyRoute.ProxyHandler()) // Proxy handler + secureRouter.PathPrefix("").Handler(proxyRoute.ProxyHandler()) // Proxy handler + + } + case OAuth: + oauth, err := oAuthMiddleware(routeMiddleware.Rule) + if err != nil { + logger.Error("Error: %s", err.Error()) + } else { + redirectURL := "/callback" + route.Path + if oauth.RedirectURL != "" { + redirectURL = oauth.RedirectURL + } + amw := middlewares.Oauth{ + ClientID: oauth.ClientID, + ClientSecret: oauth.ClientSecret, + RedirectURL: redirectURL, + Scopes: oauth.Scopes, + Endpoint: middlewares.OauthEndpoint{ + AuthURL: oauth.Endpoint.AuthURL, + TokenURL: oauth.Endpoint.TokenURL, + UserInfoURL: oauth.Endpoint.UserInfoURL, + }, + State: oauth.State, + Origins: gateway.Cors.Origins, + JWTSecret: oauth.JWTSecret, + Provider: oauth.Provider, + } + oauthRuler := oauthRulerMiddleware(amw) + // Check if a cookie path is defined + if oauthRuler.CookiePath == "" { + oauthRuler.CookiePath = route.Path + } + // Check if a RedirectPath is defined + if oauthRuler.RedirectPath == "" { + oauthRuler.RedirectPath = util.ParseRoutePath(route.Path, middlewarePath) + } + if oauthRuler.Provider == "" { + oauthRuler.Provider = "custom" + } + secureRouter.Use(amw.AuthMiddleware) + secureRouter.Use(CORSHandler(route.Cors)) + secureRouter.PathPrefix("/").Handler(proxyRoute.ProxyHandler()) // Proxy handler + secureRouter.PathPrefix("").Handler(proxyRoute.ProxyHandler()) // Proxy handler + // Callback route + r.HandleFunc(util.UrlParsePath(redirectURL), oauthRuler.callbackHandler).Methods("GET") + } + default: + if !doesExist(routeMiddleware.Type) { + logger.Error("Unknown middlewares type %s", routeMiddleware.Type) + } + + } + + } +} diff --git a/internal/route_type.go b/internal/route_type.go index acc8210..b09e894 100644 --- a/internal/route_type.go +++ b/internal/route_type.go @@ -23,9 +23,9 @@ type Route struct { Path string `yaml:"path"` // Name defines route name Name string `yaml:"name"` - //Host Domain/host based request routing - //Host string `yaml:"host"` - //Hosts Domains/hosts based request routing + // Host Domain/host based request routing + // Host string `yaml:"host"` + // Hosts Domains/hosts based request routing Hosts []string `yaml:"hosts"` // Rewrite rewrites route path to desired path // diff --git a/internal/server.go b/internal/server.go index f06f031..947f1ec 100644 --- a/internal/server.go +++ b/internal/server.go @@ -19,7 +19,6 @@ import ( "context" "crypto/tls" "errors" - "fmt" "github.com/jkaninda/goma-gateway/pkg/logger" "net/http" "os" @@ -33,9 +32,7 @@ func (gatewayServer GatewayServer) Start() error { logger.Info("Initializing routes...") route := gatewayServer.Initialize() logger.Debug("Routes count=%d, Middlewares count=%d", len(gatewayServer.gateway.Routes), len(gatewayServer.middlewares)) - if err := gatewayServer.initRedis(); err != nil { - return fmt.Errorf("failed to initialize Redis: %w", err) - } + gatewayServer.initRedis() defer gatewayServer.closeRedis() tlsConfig, listenWithTLS, err := gatewayServer.initTLS() @@ -51,9 +48,7 @@ func (gatewayServer GatewayServer) Start() error { httpsServer := gatewayServer.createServer(":8443", route, tlsConfig) // Start HTTP/HTTPS servers - if err := gatewayServer.startServers(httpServer, httpsServer, listenWithTLS); err != nil { - return err - } + gatewayServer.startServers(httpServer, httpsServer, listenWithTLS) // Handle graceful shutdown return gatewayServer.shutdown(httpServer, httpsServer, listenWithTLS) @@ -70,7 +65,7 @@ func (gatewayServer GatewayServer) createServer(addr string, handler http.Handle } } -func (gatewayServer GatewayServer) startServers(httpServer, httpsServer *http.Server, listenWithTLS bool) error { +func (gatewayServer GatewayServer) startServers(httpServer, httpsServer *http.Server, listenWithTLS bool) { go func() { logger.Info("Starting HTTP server on 0.0.0.0:8080") if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { @@ -86,8 +81,6 @@ func (gatewayServer GatewayServer) startServers(httpServer, httpsServer *http.Se } }() } - - return nil } func (gatewayServer GatewayServer) shutdown(httpServer, httpsServer *http.Server, listenWithTLS bool) error { diff --git a/internal/types.go b/internal/types.go index 7180e48..ca0c724 100644 --- a/internal/types.go +++ b/internal/types.go @@ -47,7 +47,7 @@ type JWTRuleMiddleware struct { // // In case you want to get headers from Authentication service and inject them to next request's params. // - //e.g: Header X-Auth-UserId to query userId + // e.g: Header X-Auth-UserId to query userId Params map[string]string `yaml:"params"` } type OauthRulerMiddleware struct { @@ -66,7 +66,7 @@ type OauthRulerMiddleware struct { RedirectURL string `yaml:"redirectUrl"` // RedirectPath is the PATH to redirect users after authentication, e.g: /my-protected-path/dashboard RedirectPath string `yaml:"redirectPath"` - //CookiePath e.g: /my-protected-path or / || by default is applied on a route path + // CookiePath e.g: /my-protected-path or / || by default is applied on a route path CookiePath string `yaml:"cookiePath"` // Scope specifies optional requested permissions. @@ -119,11 +119,10 @@ type GatewayServer struct { middlewares []Middleware } type ProxyRoute struct { - path string - rewrite string - destination string - backends []string - //healthCheck RouteHealthCheck + path string + rewrite string + destination string + backends []string methods []string cors Cors disableHostFording bool diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go index 3ca6d3b..492bb6a 100644 --- a/pkg/logger/logger.go +++ b/pkg/logger/logger.go @@ -55,7 +55,7 @@ func Fatal(msg string, args ...interface{}) { func Debug(msg string, args ...interface{}) { log.SetOutput(getStd(util.GetStringEnv("GOMA_ACCESS_LOG", "/dev/stdout"))) logLevel := util.GetStringEnv("GOMA_LOG_LEVEL", "") - if strings.ToLower(logLevel) == "trace" || strings.ToLower(logLevel) == "debug" { + if strings.ToLower(logLevel) == traceLog || strings.ToLower(logLevel) == "debug" { logWithCaller("DEBUG", msg, args...) } @@ -63,7 +63,7 @@ func Debug(msg string, args ...interface{}) { func Trace(msg string, args ...interface{}) { log.SetOutput(getStd(util.GetStringEnv("GOMA_ACCESS_LOG", "/dev/stdout"))) logLevel := util.GetStringEnv("GOMA_LOG_LEVEL", "") - if strings.ToLower(logLevel) == "trace" { + if strings.ToLower(logLevel) == traceLog { logWithCaller("DEBUG", msg, args...) } @@ -86,7 +86,7 @@ func logWithCaller(level, msg string, args ...interface{}) { // Log message with caller information if GOMA_LOG_LEVEL is trace logLevel := util.GetStringEnv("GOMA_LOG_LEVEL", "") if strings.ToLower(logLevel) != "off" { - if strings.ToLower(logLevel) == "trace" { + if strings.ToLower(logLevel) == traceLog { log.Printf("%s: %s (File: %s, Line: %d)\n", level, formattedMessage, file, line) } else { log.Printf("%s: %s\n", level, formattedMessage) diff --git a/pkg/logger/var.go b/pkg/logger/var.go new file mode 100644 index 0000000..578dd57 --- /dev/null +++ b/pkg/logger/var.go @@ -0,0 +1,20 @@ +/* + * Copyright 2024 Jonas Kaninda + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package logger + +const traceLog = "trace" diff --git a/util/helpers.go b/util/helpers.go index c04a42e..3248312 100644 --- a/util/helpers.go +++ b/util/helpers.go @@ -10,13 +10,14 @@ You may get a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 */ import ( - "github.com/robfig/cron/v3" "net/url" "os" "regexp" "strconv" "strings" "time" + + "github.com/robfig/cron/v3" ) // FileExists checks if the file does exist @@ -148,7 +149,7 @@ func Slug(text string) string { text = strings.ToLower(text) // Replace spaces and special characters with hyphens - re := regexp.MustCompile(`[^\w]+`) + re := regexp.MustCompile(`\W+`) text = re.ReplaceAllString(text, "-") // Remove leading and trailing hyphens