feat: add load additional middleware from a defined directory

This commit is contained in:
Jonas Kaninda
2024-11-21 16:52:08 +01:00
parent 9d02bfa2bc
commit 7369d5eebf
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
ENV TZ=UTC
ARG WORKDIR="/etc/goma/"
ARG WORKDIR="/etc/goma"
ARG EXTRADIR="${WORKDIR}/extra"
ARG appVersion=""
ARG user="goma"
LABEL author="Jonas Kaninda"
LABEL version=${appVersion}
LABEL github="github.com/jkaninda/goma-gateway"
RUN mkdir -p ${WORKDIR} && \
chmod a+rw ${WORKDIR}
RUN mkdir -p ${WORKDIR} ${EXTRADIR} && \
chmod a+rw ${WORKDIR} ${EXTRADIR}
COPY --from=build /app/goma /usr/local/bin/goma
RUN chmod a+x /usr/local/bin/goma && \
ln -s /usr/local/bin/goma /usr/bin/goma

View File

@@ -2,6 +2,9 @@ package pkg
import (
"errors"
"fmt"
"gopkg.in/yaml.v3"
"os"
"slices"
"strings"
)
@@ -32,3 +35,45 @@ func GetMiddleware(rule string, middlewares []Middleware) (Middleware, error) {
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...)
}
if len(extraRoutes) == 0 {
return nil, fmt.Errorf("no extra routes found")
}
return extraRoutes, nil
}

View File

@@ -61,3 +61,7 @@ type ExtraRoute struct {
// Routes holds proxy 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 {
gateway := gatewayServer.gateway
dynamicRoutes = gateway.Routes
// Load Extra Routes
if len(gateway.ExtraRoutes.Directory) != 0 {
logger.Info("Loading additional routes from %s", gateway.ExtraRoutes.Directory)
extraRoutes, err := loadExtraRoutes(gateway.ExtraRoutes.Directory)
if err != nil {
logger.Error("Error: %v", err.Error())
dynamicMiddlewares = gatewayServer.middlewares
if len(gateway.ExtraRoutes.Directory) == 0 {
gateway.ExtraRoutes.Directory = ExtraDir
}
if len(extraRoutes) == 0 {
logger.Info("no extra routes found in %s", gateway.ExtraRoutes.Directory)
} else {
// Load Extra Middlewares
logger.Info("Loading additional configurations...")
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...)
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
duplicates := findDuplicateRouteNames(dynamicRoutes)
duplicates = findDuplicateRouteNames(dynamicRoutes)
if len(duplicates) != 0 {
for _, duplicate := range duplicates {
logger.Error("Duplicated route name was found: %s ", duplicate)
}
}
m := gatewayServer.middlewares
m := dynamicMiddlewares
redisBased := false
if len(gateway.Redis.Addr) != 0 {
redisBased = true

View File

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