feat: add additional routes from defined directory
This commit is contained in:
@@ -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 {
|
||||
|
||||
47
internal/extra_config.go
Normal file
47
internal/extra_config.go
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 pkg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// loadExtraFiles loads routes files in .yml and .yaml based on defined directory
|
||||
func loadExtraFiles(routePath string) ([]string, error) {
|
||||
// Slice to store YAML/YML files
|
||||
var yamlFiles []string
|
||||
// Walk through the Directory
|
||||
err := filepath.Walk(routePath, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Check for .yaml or .yml file extension
|
||||
if !info.IsDir() && (filepath.Ext(path) == ".yaml" || filepath.Ext(path) == ".yml") {
|
||||
yamlFiles = append(yamlFiles, path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
//log.Fatalf("error walking the path %v: %v", routePath, err)
|
||||
return nil, fmt.Errorf("error loading extra route files: %v", err)
|
||||
}
|
||||
return yamlFiles, nil
|
||||
}
|
||||
@@ -38,6 +38,7 @@ type Gateway struct {
|
||||
AccessLog string `yaml:"accessLog" env:"GOMA_ACCESS_LOG, overwrite"`
|
||||
ErrorLog string `yaml:"errorLog" env:"GOMA_ERROR_LOG=, overwrite"`
|
||||
LogLevel string `yaml:"logLevel" env:"GOMA_LOG_LEVEL, overwrite"`
|
||||
ExtraRoutes ExtraRouteConfig `yaml:"extraRoutes"`
|
||||
// DisableHealthCheckStatus enable and disable routes health check
|
||||
DisableHealthCheckStatus bool `yaml:"disableHealthCheckStatus"`
|
||||
// DisableRouteHealthCheckError allows enabling and disabling backend healthcheck errors
|
||||
|
||||
@@ -35,18 +35,27 @@ func init() {
|
||||
// Initialize initializes the routes
|
||||
func (gatewayServer GatewayServer) Initialize() *mux.Router {
|
||||
gateway := gatewayServer.gateway
|
||||
dynamicRoutes = gateway.Routes
|
||||
// Load Extra Routes
|
||||
if len(gateway.ExtraRoutes.Directory) != 0 {
|
||||
extraRoutes, err := loadExtraRoutes(gateway.ExtraRoutes.Directory)
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
}
|
||||
dynamicRoutes = append(dynamicRoutes, extraRoutes...)
|
||||
}
|
||||
m := gatewayServer.middlewares
|
||||
redisBased := false
|
||||
if len(gateway.Redis.Addr) != 0 {
|
||||
redisBased = true
|
||||
}
|
||||
// Routes background healthcheck
|
||||
routesHealthCheck(gateway.Routes)
|
||||
routesHealthCheck(dynamicRoutes)
|
||||
|
||||
r := mux.NewRouter()
|
||||
heath := HealthCheckRoute{
|
||||
DisableRouteHealthCheckError: gateway.DisableRouteHealthCheckError,
|
||||
Routes: gateway.Routes,
|
||||
Routes: dynamicRoutes,
|
||||
}
|
||||
if gateway.EnableMetrics {
|
||||
// Prometheus endpoint
|
||||
@@ -80,7 +89,7 @@ func (gatewayServer GatewayServer) Initialize() *mux.Router {
|
||||
// Add rate limit middlewares
|
||||
r.Use(limiter.RateLimitMiddleware())
|
||||
}
|
||||
for rIndex, route := range gateway.Routes {
|
||||
for rIndex, route := range dynamicRoutes {
|
||||
if len(route.Path) != 0 {
|
||||
// Checks if route destination and backend are empty
|
||||
if len(route.Destination) == 0 && len(route.Backends) == 0 {
|
||||
|
||||
55
internal/route_config.go
Normal file
55
internal/route_config.go
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 pkg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jkaninda/goma-gateway/pkg/logger"
|
||||
"gopkg.in/yaml.v3"
|
||||
"os"
|
||||
)
|
||||
|
||||
// loadExtraRoutes loads additional routes
|
||||
func loadExtraRoutes(routePath string) ([]Route, error) {
|
||||
logger.Info("Loading additional routes from %s", routePath)
|
||||
yamlFiles, err := loadExtraFiles(routePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error loading extra files: %v", err)
|
||||
}
|
||||
var extraRoutes []Route
|
||||
for _, yamlFile := range yamlFiles {
|
||||
buf, err := os.ReadFile(yamlFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error loading extra file: %v", err)
|
||||
}
|
||||
ex := &ExtraRoute{}
|
||||
err = yaml.Unmarshal(buf, ex)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("in file %q: %w", ConfigFile, err)
|
||||
}
|
||||
extraRoutes = append(extraRoutes, ex.Routes...)
|
||||
|
||||
}
|
||||
if len(extraRoutes) == 0 {
|
||||
return nil, fmt.Errorf("no extra routes found in %s", routePath)
|
||||
} else {
|
||||
logger.Info("Loaded %d extra routes from %s", len(extraRoutes), routePath)
|
||||
|
||||
}
|
||||
return extraRoutes, nil
|
||||
}
|
||||
@@ -56,3 +56,8 @@ type Route struct {
|
||||
// Middlewares Defines route middlewares from Middleware names
|
||||
Middlewares []string `yaml:"middlewares"`
|
||||
}
|
||||
|
||||
type ExtraRoute struct {
|
||||
// Routes holds proxy routes
|
||||
Routes []Route `yaml:"routes"`
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ func (gatewayServer GatewayServer) Start() error {
|
||||
}
|
||||
|
||||
if !gatewayServer.gateway.DisableDisplayRouteOnStart {
|
||||
printRoute(gatewayServer.gateway.Routes)
|
||||
printRoute(dynamicRoutes)
|
||||
}
|
||||
|
||||
httpServer := gatewayServer.createServer(":8080", route, nil)
|
||||
|
||||
@@ -168,3 +168,8 @@ type Redis struct {
|
||||
Addr string `yaml:"addr"`
|
||||
Password string `yaml:"password"`
|
||||
}
|
||||
|
||||
type ExtraRouteConfig struct {
|
||||
Directory string `yaml:"directory"`
|
||||
Watch bool `yaml:"watch"`
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ const AccessMiddleware = "access" // access middlewares
|
||||
const BasicAuth = "basic" // basic authentication middlewares
|
||||
const JWTAuth = "jwt" // JWT authentication middlewares
|
||||
const OAuth = "oauth" // OAuth authentication middlewares
|
||||
var (
|
||||
// Round-robin counter
|
||||
var counter uint32
|
||||
|
||||
var Routes *[]Route
|
||||
counter uint32
|
||||
// dynamicRoutes routes
|
||||
dynamicRoutes []Route
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user