mirror of
https://github.com/yusing/godoxy.git
synced 2026-02-23 10:54:50 +01:00
This is a large-scale refactoring across the codebase that replaces the custom `gperr.Error` type with Go's standard `error` interface. The changes include: - Replacing `gperr.Error` return types with `error` in function signatures - Using `errors.New()` and `fmt.Errorf()` instead of `gperr.New()` and `gperr.Errorf()` - Using `%w` format verb for error wrapping instead of `.With()` method - Replacing `gperr.Subject()` calls with `gperr.PrependSubject()` - Converting error logging from `gperr.Log*()` functions to zerolog's `.Err().Msg()` pattern - Update NewLogger to handle multiline error message - Updating `goutils` submodule to latest commit This refactoring aligns with Go idioms and removes the dependency on custom error handling abstractions in favor of standard library patterns.
109 lines
2.6 KiB
Go
109 lines
2.6 KiB
Go
package middleware
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"sort"
|
|
|
|
"github.com/goccy/go-yaml"
|
|
gperr "github.com/yusing/goutils/errs"
|
|
)
|
|
|
|
var ErrMissingMiddlewareUse = errors.New("missing middleware 'use' field")
|
|
|
|
func BuildMiddlewaresFromComposeFile(filePath string, eb *gperr.Builder) map[string]*Middleware {
|
|
fileContent, err := os.ReadFile(filePath)
|
|
if err != nil {
|
|
eb.Add(err)
|
|
return nil
|
|
}
|
|
return BuildMiddlewaresFromYAML(path.Base(filePath), fileContent, eb)
|
|
}
|
|
|
|
func BuildMiddlewaresFromYAML(source string, data []byte, eb *gperr.Builder) map[string]*Middleware {
|
|
var rawMap map[string][]map[string]any
|
|
err := yaml.Unmarshal(data, &rawMap)
|
|
if err != nil {
|
|
eb.Add(err)
|
|
return nil
|
|
}
|
|
middlewares := make(map[string]*Middleware)
|
|
for name, defs := range rawMap {
|
|
chain, err := BuildMiddlewareFromChainRaw(name, defs)
|
|
if err != nil {
|
|
eb.AddSubject(err, source)
|
|
} else {
|
|
middlewares[name+"@file"] = chain
|
|
}
|
|
}
|
|
return middlewares
|
|
}
|
|
|
|
func compileMiddlewares(middlewaresMap map[string]OptionsRaw) ([]*Middleware, error) {
|
|
middlewares := make([]*Middleware, 0, len(middlewaresMap))
|
|
|
|
var errs gperr.Builder
|
|
var invalidOpts gperr.Builder
|
|
|
|
for name, opts := range middlewaresMap {
|
|
m, err := Get(name)
|
|
if err != nil {
|
|
errs.Add(err)
|
|
continue
|
|
}
|
|
|
|
m, err = m.New(opts)
|
|
if err != nil {
|
|
invalidOpts.AddSubjectf(err, "middlewares.%s", name)
|
|
continue
|
|
}
|
|
middlewares = append(middlewares, m)
|
|
}
|
|
|
|
if invalidOpts.HasError() {
|
|
errs.Add(invalidOpts.Error())
|
|
}
|
|
sort.Sort(ByPriority(middlewares))
|
|
return middlewares, errs.Error()
|
|
}
|
|
|
|
func BuildMiddlewareFromMap(name string, middlewaresMap map[string]OptionsRaw) (*Middleware, error) {
|
|
compiled, err := compileMiddlewares(middlewaresMap)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return NewMiddlewareChain(name, compiled), nil
|
|
}
|
|
|
|
// TODO: check conflict or duplicates.
|
|
func BuildMiddlewareFromChainRaw(name string, defs []map[string]any) (*Middleware, error) {
|
|
var chainErr gperr.Builder
|
|
chain := make([]*Middleware, 0, len(defs))
|
|
for i, def := range defs {
|
|
if def["use"] == nil || def["use"] == "" {
|
|
chainErr.AddSubjectf(ErrMissingMiddlewareUse, "%s[%d]", name, i)
|
|
continue
|
|
}
|
|
baseName := def["use"].(string)
|
|
base, err := Get(baseName)
|
|
if err != nil {
|
|
chainErr.AddSubjectf(err, "%s[%d]", name, i)
|
|
continue
|
|
}
|
|
delete(def, "use")
|
|
m, err := base.New(def)
|
|
if err != nil {
|
|
chainErr.AddSubjectf(err, "%s[%d]", name, i)
|
|
continue
|
|
}
|
|
m.name = fmt.Sprintf("%s[%d]", name, i)
|
|
chain = append(chain, m)
|
|
}
|
|
if chainErr.HasError() {
|
|
return nil, chainErr.Error()
|
|
}
|
|
return NewMiddlewareChain(name, chain), nil
|
|
}
|