Merge pull request #124 from jkaninda/develop

feat: add load additional middleware from a defined directory
This commit is contained in:
2024-11-21 17:00:22 +01:00
committed by GitHub
6 changed files with 86 additions and 18 deletions

View File

@@ -13,15 +13,16 @@ RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-X 'github.com/jkaninda/goma-gat
FROM alpine:3.20.3 FROM alpine:3.20.3
ENV TZ=UTC ENV TZ=UTC
ARG WORKDIR="/etc/goma/" ARG WORKDIR="/etc/goma"
ARG EXTRADIR="${WORKDIR}/extra"
ARG appVersion="" ARG appVersion=""
ARG user="goma" ARG user="goma"
LABEL author="Jonas Kaninda" LABEL author="Jonas Kaninda"
LABEL version=${appVersion} LABEL version=${appVersion}
LABEL github="github.com/jkaninda/goma-gateway" LABEL github="github.com/jkaninda/goma-gateway"
RUN mkdir -p ${WORKDIR} && \ RUN mkdir -p ${WORKDIR} ${EXTRADIR} && \
chmod a+rw ${WORKDIR} chmod a+rw ${WORKDIR} ${EXTRADIR}
COPY --from=build /app/goma /usr/local/bin/goma COPY --from=build /app/goma /usr/local/bin/goma
RUN chmod a+x /usr/local/bin/goma && \ RUN chmod a+x /usr/local/bin/goma && \
ln -s /usr/local/bin/goma /usr/bin/goma ln -s /usr/local/bin/goma /usr/bin/goma

View File

@@ -2,6 +2,9 @@ package pkg
import ( import (
"errors" "errors"
"fmt"
"gopkg.in/yaml.v3"
"os"
"slices" "slices"
"strings" "strings"
) )
@@ -32,3 +35,45 @@ func GetMiddleware(rule string, middlewares []Middleware) (Middleware, error) {
return Middleware{}, errors.New("no middlewares found with name " + rule) return Middleware{}, errors.New("no middlewares found with name " + rule)
} }
// loadExtraMiddlewares loads additional middlewares
func loadExtraMiddlewares(routePath string) ([]Middleware, error) {
yamlFiles, err := loadExtraFiles(routePath)
if err != nil {
return nil, fmt.Errorf("error loading extra files: %v", err)
}
var extraMiddlewares []Middleware
for _, yamlFile := range yamlFiles {
buf, err := os.ReadFile(yamlFile)
if err != nil {
return nil, fmt.Errorf("error loading extra file: %v", err)
}
ex := &ExtraMiddleware{}
err = yaml.Unmarshal(buf, ex)
if err != nil {
return nil, fmt.Errorf("in file %q: %w", ConfigFile, err)
}
extraMiddlewares = append(extraMiddlewares, ex.Middlewares...)
}
if len(extraMiddlewares) == 0 {
return nil, fmt.Errorf("no extra middleware found")
}
return extraMiddlewares, nil
}
// findDuplicateMiddlewareNames finds duplicated middleware name
func findDuplicateMiddlewareNames(middlewares []Middleware) []string {
// Create a map to track occurrences of names
nameMap := make(map[string]int)
var duplicates []string
for _, mid := range middlewares {
nameMap[mid.Name]++
// If the count is ==2, it's a duplicate
if nameMap[mid.Name] == 2 {
duplicates = append(duplicates, mid.Name)
}
}
return duplicates
}

View File

@@ -43,6 +43,9 @@ func loadExtraRoutes(routePath string) ([]Route, error) {
extraRoutes = append(extraRoutes, ex.Routes...) extraRoutes = append(extraRoutes, ex.Routes...)
} }
if len(extraRoutes) == 0 {
return nil, fmt.Errorf("no extra routes found")
}
return extraRoutes, nil return extraRoutes, nil
} }

View File

@@ -61,3 +61,7 @@ type ExtraRoute struct {
// Routes holds proxy routes // Routes holds proxy routes
Routes []Route `yaml:"routes"` Routes []Route `yaml:"routes"`
} }
type ExtraMiddleware struct {
// Routes holds proxy routes
Middlewares []Middleware `yaml:"middlewares"`
}

View File

@@ -37,28 +37,41 @@ func init() {
func (gatewayServer GatewayServer) Initialize() *mux.Router { func (gatewayServer GatewayServer) Initialize() *mux.Router {
gateway := gatewayServer.gateway gateway := gatewayServer.gateway
dynamicRoutes = gateway.Routes dynamicRoutes = gateway.Routes
// Load Extra Routes dynamicMiddlewares = gatewayServer.middlewares
if len(gateway.ExtraRoutes.Directory) != 0 { if len(gateway.ExtraRoutes.Directory) == 0 {
logger.Info("Loading additional routes from %s", gateway.ExtraRoutes.Directory) gateway.ExtraRoutes.Directory = ExtraDir
extraRoutes, err := loadExtraRoutes(gateway.ExtraRoutes.Directory)
if err != nil {
logger.Error("Error: %v", err.Error())
} }
if len(extraRoutes) == 0 { // Load Extra Middlewares
logger.Info("no extra routes found in %s", gateway.ExtraRoutes.Directory) logger.Info("Loading additional configurations...")
} else { extraMiddlewares, err := loadExtraMiddlewares(gateway.ExtraRoutes.Directory)
if err == nil {
dynamicMiddlewares = append(dynamicMiddlewares, extraMiddlewares...)
logger.Info("Loaded %d additional middlewares", len(extraMiddlewares))
}
// Load Extra Routes
extraRoutes, err := loadExtraRoutes(gateway.ExtraRoutes.Directory)
if err == nil {
dynamicRoutes = append(dynamicRoutes, extraRoutes...) dynamicRoutes = append(dynamicRoutes, extraRoutes...)
logger.Info("Loaded %d extra routes from %s", len(extraRoutes), gateway.ExtraRoutes.Directory) logger.Info("Loaded %d additional routes", len(extraRoutes))
}
// find duplicated middleware name
duplicates := findDuplicateMiddlewareNames(dynamicMiddlewares)
if len(duplicates) != 0 {
for _, duplicate := range duplicates {
logger.Fatal("Duplicated middleware name: %s, the name of the middleware should be unique.", duplicate)
} }
} }
// find duplicated route name // find duplicated route name
duplicates := findDuplicateRouteNames(dynamicRoutes) duplicates = findDuplicateRouteNames(dynamicRoutes)
if len(duplicates) != 0 { if len(duplicates) != 0 {
for _, duplicate := range duplicates { for _, duplicate := range duplicates {
logger.Error("Duplicated route name was found: %s ", duplicate) logger.Error("Duplicated route name was found: %s ", duplicate)
} }
} }
m := gatewayServer.middlewares m := dynamicMiddlewares
redisBased := false redisBased := false
if len(gateway.Redis.Addr) != 0 { if len(gateway.Redis.Addr) != 0 {
redisBased = true redisBased = true

View File

@@ -1,6 +1,7 @@
package pkg package pkg
const ConfigDir = "/etc/goma/" // Default configuration file const ConfigDir = "/etc/goma/" // Default configuration file
const ExtraDir = ConfigDir + "extra"
const ConfigFile = "/etc/goma/goma.yml" // Default configuration file const ConfigFile = "/etc/goma/goma.yml" // Default configuration file
const accessControlAllowOrigin = "Access-Control-Allow-Origin" // Cors const accessControlAllowOrigin = "Access-Control-Allow-Origin" // Cors
const gatewayName = "Goma Gateway" const gatewayName = "Goma Gateway"
@@ -13,4 +14,5 @@ var (
counter uint32 counter uint32
// dynamicRoutes routes // dynamicRoutes routes
dynamicRoutes []Route dynamicRoutes []Route
dynamicMiddlewares []Middleware
) )