feat: add load additional middleware from a defined directory
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
dynamicMiddlewares = gatewayServer.middlewares
|
||||||
|
if len(gateway.ExtraRoutes.Directory) == 0 {
|
||||||
|
gateway.ExtraRoutes.Directory = ExtraDir
|
||||||
|
}
|
||||||
|
// 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
|
// Load Extra Routes
|
||||||
if len(gateway.ExtraRoutes.Directory) != 0 {
|
extraRoutes, err := loadExtraRoutes(gateway.ExtraRoutes.Directory)
|
||||||
logger.Info("Loading additional routes from %s", gateway.ExtraRoutes.Directory)
|
if err == nil {
|
||||||
extraRoutes, err := loadExtraRoutes(gateway.ExtraRoutes.Directory)
|
dynamicRoutes = append(dynamicRoutes, extraRoutes...)
|
||||||
if err != nil {
|
logger.Info("Loaded %d additional routes", len(extraRoutes))
|
||||||
logger.Error("Error: %v", err.Error())
|
|
||||||
}
|
}
|
||||||
if len(extraRoutes) == 0 {
|
|
||||||
logger.Info("no extra routes found in %s", gateway.ExtraRoutes.Directory)
|
// find duplicated middleware name
|
||||||
} else {
|
duplicates := findDuplicateMiddlewareNames(dynamicMiddlewares)
|
||||||
dynamicRoutes = append(dynamicRoutes, extraRoutes...)
|
if len(duplicates) != 0 {
|
||||||
logger.Info("Loaded %d extra routes from %s", len(extraRoutes), gateway.ExtraRoutes.Directory)
|
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
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -12,5 +13,6 @@ var (
|
|||||||
// Round-robin counter
|
// Round-robin counter
|
||||||
counter uint32
|
counter uint32
|
||||||
// dynamicRoutes routes
|
// dynamicRoutes routes
|
||||||
dynamicRoutes []Route
|
dynamicRoutes []Route
|
||||||
|
dynamicMiddlewares []Middleware
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user