mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-22 16:28:30 +02:00
refactor(errs): migrate from gperr.Error to standard Go error interface
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.
This commit is contained in:
@@ -93,8 +93,8 @@ const (
|
||||
|
||||
```go
|
||||
// Validation and lifecycle
|
||||
func (r *Route) Validate() gperr.Error
|
||||
func (r *Route) Start(parent task.Parent) gperr.Error
|
||||
func (r *Route) Validate() error
|
||||
func (r *Route) Start(parent task.Parent) error
|
||||
func (r *Route) Finish(reason any)
|
||||
func (r *Route) Started() <-chan struct{}
|
||||
|
||||
@@ -119,8 +119,8 @@ func (r *Route) UseHealthCheck() bool
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Route {
|
||||
+Validate() gperr.Error
|
||||
+Start(parent) gperr.Error
|
||||
+Validate() error
|
||||
+Start(parent) error
|
||||
+Finish(reason)
|
||||
+Started() <-chan struct#123;#125;
|
||||
}
|
||||
|
||||
@@ -2,16 +2,16 @@ package route
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
entrypoint "github.com/yusing/godoxy/internal/entrypoint/types"
|
||||
"github.com/yusing/godoxy/internal/types"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
)
|
||||
|
||||
// checkExists checks if the route already exists in the entrypoint.
|
||||
//
|
||||
// Context must be passed from the parent task that carries the entrypoint value.
|
||||
func checkExists(ctx context.Context, r types.Route) gperr.Error {
|
||||
func checkExists(ctx context.Context, r types.Route) error {
|
||||
if r.UseLoadBalance() { // skip checking for load balanced routes
|
||||
return nil
|
||||
}
|
||||
@@ -26,7 +26,7 @@ func checkExists(ctx context.Context, r types.Route) gperr.Error {
|
||||
existing, ok = entrypoint.FromCtx(ctx).StreamRoutes().Get(r.Key())
|
||||
}
|
||||
if ok {
|
||||
return gperr.Errorf("route already exists: from provider %s and %s", existing.ProviderName(), r.ProviderName())
|
||||
return fmt.Errorf("route already exists: from provider %s and %s", existing.ProviderName(), r.ProviderName())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
@@ -50,12 +51,12 @@ func handler(root string, spa bool, index string) http.Handler {
|
||||
})
|
||||
}
|
||||
|
||||
func NewFileServer(base *Route) (*FileServer, gperr.Error) {
|
||||
func NewFileServer(base *Route) (*FileServer, error) {
|
||||
s := &FileServer{Route: base}
|
||||
|
||||
s.Root = filepath.Clean(s.Root)
|
||||
if !path.IsAbs(s.Root) {
|
||||
return nil, gperr.New("`root` must be an absolute path")
|
||||
return nil, errors.New("`root` must be an absolute path")
|
||||
}
|
||||
|
||||
if s.Index == "" {
|
||||
@@ -77,7 +78,7 @@ func NewFileServer(base *Route) (*FileServer, gperr.Error) {
|
||||
}
|
||||
|
||||
// Start implements task.TaskStarter.
|
||||
func (s *FileServer) Start(parent task.Parent) gperr.Error {
|
||||
func (s *FileServer) Start(parent task.Parent) error {
|
||||
s.task = parent.Subtask("fileserver."+s.Name(), false)
|
||||
|
||||
pathPatterns := s.PathPatterns
|
||||
@@ -109,7 +110,7 @@ func (s *FileServer) Start(parent task.Parent) gperr.Error {
|
||||
s.accessLogger, err = accesslog.NewAccessLogger(s.task, s.AccessLog)
|
||||
if err != nil {
|
||||
s.task.Finish(err)
|
||||
return gperr.Wrap(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,14 +128,14 @@ func (s *FileServer) Start(parent task.Parent) gperr.Error {
|
||||
|
||||
ep := entrypoint.FromCtx(parent.Context())
|
||||
if ep == nil {
|
||||
err := gperr.New("entrypoint not initialized")
|
||||
err := errors.New("entrypoint not initialized")
|
||||
s.task.Finish(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ep.StartAddRoute(s); err != nil {
|
||||
s.task.Finish(err)
|
||||
return gperr.Wrap(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ type ProviderImpl interface {
|
||||
fmt.Stringer
|
||||
ShortName() string
|
||||
IsExplicitOnly() bool
|
||||
loadRoutesImpl() (route.Routes, gperr.Error)
|
||||
loadRoutesImpl() (route.Routes, error)
|
||||
NewWatcher() W.Watcher
|
||||
Logger() *zerolog.Logger
|
||||
}
|
||||
@@ -62,8 +62,8 @@ func NewAgentProvider(cfg *agent.AgentConfig) *Provider
|
||||
|
||||
```go
|
||||
func (p *Provider) GetType() provider.Type
|
||||
func (p *Provider) Start(parent task.Parent) gperr.Error
|
||||
func (p *Provider) LoadRoutes() gperr.Error
|
||||
func (p *Provider) Start(parent task.Parent) error
|
||||
func (p *Provider) LoadRoutes() error
|
||||
func (p *Provider) IterRoutes(yield func(string, types.Route) bool)
|
||||
func (p *Provider) GetRoute(alias string) (types.Route, bool)
|
||||
func (p *Provider) FindService(project, service string) (types.Route, bool)
|
||||
@@ -80,8 +80,8 @@ classDiagram
|
||||
+t provider.Type
|
||||
+routes route.Routes
|
||||
+watcher W.Watcher
|
||||
+Start(parent) gperr.Error
|
||||
+LoadRoutes() gperr.Error
|
||||
+Start(parent) error
|
||||
+LoadRoutes() error
|
||||
+IterRoutes(yield)
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ classDiagram
|
||||
+String() string
|
||||
+ShortName() string
|
||||
+IsExplicitOnly() bool
|
||||
+loadRoutesImpl() (route.Routes, gperr.Error)
|
||||
+loadRoutesImpl() (route.Routes, error)
|
||||
+NewWatcher() W.Watcher
|
||||
+Logger() *zerolog.Logger
|
||||
}
|
||||
@@ -99,20 +99,20 @@ classDiagram
|
||||
+name string
|
||||
+dockerCfg types.DockerProviderConfig
|
||||
+ShortName() string
|
||||
+loadRoutesImpl() (route.Routes, gperr.Error)
|
||||
+loadRoutesImpl() (route.Routes, error)
|
||||
}
|
||||
|
||||
class FileProviderImpl {
|
||||
+filename string
|
||||
+ShortName() string
|
||||
+loadRoutesImpl() (route.Routes, gperr.Error)
|
||||
+loadRoutesImpl() (route.Routes, error)
|
||||
}
|
||||
|
||||
class AgentProviderImpl {
|
||||
+*agent.AgentConfig
|
||||
+docker DockerProviderImpl
|
||||
+ShortName() string
|
||||
+loadRoutesImpl() (route.Routes, gperr.Error)
|
||||
+loadRoutesImpl() (route.Routes, error)
|
||||
}
|
||||
|
||||
Provider --> ProviderImpl : wraps
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"github.com/yusing/godoxy/agent/pkg/agent"
|
||||
"github.com/yusing/godoxy/internal/route"
|
||||
"github.com/yusing/godoxy/internal/watcher"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
)
|
||||
|
||||
type AgentProvider struct {
|
||||
@@ -25,7 +24,7 @@ func (p *AgentProvider) IsExplicitOnly() bool {
|
||||
return p.docker.IsExplicitOnly()
|
||||
}
|
||||
|
||||
func (p *AgentProvider) loadRoutesImpl() (route.Routes, gperr.Error) {
|
||||
func (p *AgentProvider) loadRoutesImpl() (route.Routes, error) {
|
||||
return p.docker.loadRoutesImpl()
|
||||
}
|
||||
|
||||
|
||||
@@ -58,13 +58,13 @@ func (p *DockerProvider) NewWatcher() watcher.Watcher {
|
||||
return watcher.NewDockerWatcher(p.dockerCfg)
|
||||
}
|
||||
|
||||
func (p *DockerProvider) loadRoutesImpl() (route.Routes, gperr.Error) {
|
||||
func (p *DockerProvider) loadRoutesImpl() (route.Routes, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
containers, err := docker.ListContainers(ctx, p.dockerCfg)
|
||||
if err != nil {
|
||||
return nil, gperr.Wrap(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
errs := gperr.NewBuilder("")
|
||||
@@ -74,21 +74,21 @@ func (p *DockerProvider) loadRoutesImpl() (route.Routes, gperr.Error) {
|
||||
container := docker.FromDocker(&c, p.dockerCfg)
|
||||
|
||||
if container.Errors != nil {
|
||||
errs.Add(gperr.PrependSubject(container.ContainerName, container.Errors))
|
||||
errs.AddSubject(container.Errors, container.ContainerName)
|
||||
continue
|
||||
}
|
||||
|
||||
if container.IsHostNetworkMode {
|
||||
err := docker.UpdatePorts(ctx, container)
|
||||
if err != nil {
|
||||
errs.Add(gperr.PrependSubject(container.ContainerName, err))
|
||||
errs.AddSubject(err, container.ContainerName)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
newEntries, err := p.routesFromContainerLabels(container)
|
||||
if err != nil {
|
||||
errs.Add(err.Subject(container.ContainerName))
|
||||
errs.AddSubject(err, container.ContainerName)
|
||||
}
|
||||
for k, v := range newEntries {
|
||||
if conflict, ok := routes[k]; ok {
|
||||
@@ -97,7 +97,7 @@ func (p *DockerProvider) loadRoutesImpl() (route.Routes, gperr.Error) {
|
||||
Addf("container %s", container.ContainerName).
|
||||
Addf("conflicting container %s", conflict.Container.ContainerName)
|
||||
if conflict.ShouldExclude() || v.ShouldExclude() {
|
||||
gperr.LogWarn("skipping conflicting route", err)
|
||||
log.Warn().Err(err).Msg("skipping conflicting route")
|
||||
} else {
|
||||
errs.Add(err)
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func (p *DockerProvider) loadRoutesImpl() (route.Routes, gperr.Error) {
|
||||
|
||||
// Returns a list of proxy entries for a container.
|
||||
// Always non-nil.
|
||||
func (p *DockerProvider) routesFromContainerLabels(container *types.Container) (route.Routes, gperr.Error) {
|
||||
func (p *DockerProvider) routesFromContainerLabels(container *types.Container) (route.Routes, error) {
|
||||
if !container.IsExplicit && p.IsExplicitOnly() {
|
||||
return make(route.Routes, 0), nil
|
||||
}
|
||||
@@ -150,7 +150,7 @@ func (p *DockerProvider) routesFromContainerLabels(container *types.Container) (
|
||||
panic(fmt.Errorf("invalid entry map type %T", entryMapAny))
|
||||
}
|
||||
if err := yaml.Unmarshal([]byte(yamlStr), &entryMap); err != nil {
|
||||
errs.Add(gperr.Wrap(err).Subject(alias))
|
||||
errs.AddSubject(err, alias)
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -185,7 +185,7 @@ func (p *DockerProvider) routesFromContainerLabels(container *types.Container) (
|
||||
// deserialize map into entry object
|
||||
err := serialization.MapUnmarshalValidate(entryMap, r)
|
||||
if err != nil {
|
||||
errs.Add(err.Subject(alias))
|
||||
errs.AddSubject(err, alias)
|
||||
} else {
|
||||
routes[alias] = r
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ func (handler *EventHandler) match(event watcher.Event, route *route.Route) bool
|
||||
func (handler *EventHandler) Add(parent task.Parent, route *route.Route) {
|
||||
err := handler.provider.startRoute(parent, route)
|
||||
if err != nil {
|
||||
handler.errs.Add(err.Subject("add"))
|
||||
handler.errs.AddSubjectf(err, "add")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ func (handler *EventHandler) Update(parent task.Parent, oldRoute *route.Route, n
|
||||
oldRoute.FinishAndWait("route update")
|
||||
err := handler.provider.startRoute(parent, newRoute)
|
||||
if err != nil {
|
||||
handler.errs.Add(err.Subject("update"))
|
||||
handler.errs.AddSubjectf(err, "update")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/yusing/godoxy/internal/route"
|
||||
"github.com/yusing/godoxy/internal/serialization"
|
||||
W "github.com/yusing/godoxy/internal/watcher"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
)
|
||||
|
||||
type FileProvider struct {
|
||||
@@ -34,7 +33,7 @@ func FileProviderImpl(filename string) (ProviderImpl, error) {
|
||||
return impl, nil
|
||||
}
|
||||
|
||||
func removeXPrefix(m map[string]any) gperr.Error {
|
||||
func removeXPrefix(m map[string]any) error {
|
||||
for alias := range m {
|
||||
if strings.HasPrefix(alias, "x-") {
|
||||
delete(m, alias)
|
||||
@@ -43,12 +42,12 @@ func removeXPrefix(m map[string]any) gperr.Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validate(data []byte) (routes route.Routes, err gperr.Error) {
|
||||
func validate(data []byte) (routes route.Routes, err error) {
|
||||
err = serialization.UnmarshalValidate(data, &routes, yaml.Unmarshal, removeXPrefix)
|
||||
return routes, err
|
||||
}
|
||||
|
||||
func Validate(data []byte) (err gperr.Error) {
|
||||
func Validate(data []byte) (err error) {
|
||||
_, err = validate(data)
|
||||
return err
|
||||
}
|
||||
@@ -69,16 +68,16 @@ func (p *FileProvider) Logger() *zerolog.Logger {
|
||||
return &p.l
|
||||
}
|
||||
|
||||
func (p *FileProvider) loadRoutesImpl() (route.Routes, gperr.Error) {
|
||||
func (p *FileProvider) loadRoutesImpl() (route.Routes, error) {
|
||||
data, err := os.ReadFile(p.path)
|
||||
if err != nil {
|
||||
return nil, gperr.Wrap(err)
|
||||
return nil, err
|
||||
}
|
||||
routes, err := validate(data)
|
||||
if err != nil && len(routes) == 0 {
|
||||
return nil, gperr.Wrap(err)
|
||||
return nil, err
|
||||
}
|
||||
return routes, gperr.Wrap(err)
|
||||
return routes, err
|
||||
}
|
||||
|
||||
func (p *FileProvider) NewWatcher() W.Watcher {
|
||||
|
||||
@@ -34,7 +34,7 @@ type (
|
||||
fmt.Stringer
|
||||
ShortName() string
|
||||
IsExplicitOnly() bool
|
||||
loadRoutesImpl() (route.Routes, gperr.Error)
|
||||
loadRoutesImpl() (route.Routes, error)
|
||||
NewWatcher() W.Watcher
|
||||
Logger() *zerolog.Logger
|
||||
}
|
||||
@@ -96,7 +96,7 @@ func (p *Provider) MarshalText() ([]byte, error) {
|
||||
}
|
||||
|
||||
// Start implements task.TaskStarter.
|
||||
func (p *Provider) Start(parent task.Parent) gperr.Error {
|
||||
func (p *Provider) Start(parent task.Parent) error {
|
||||
errs := gperr.NewGroup("routes error")
|
||||
|
||||
t := parent.Subtask("provider."+p.String(), false)
|
||||
@@ -124,8 +124,8 @@ func (p *Provider) Start(parent task.Parent) gperr.Error {
|
||||
handler.Handle(t, events)
|
||||
handler.Log()
|
||||
},
|
||||
func(err gperr.Error) {
|
||||
gperr.LogError("event error", err, p.Logger())
|
||||
func(err error) {
|
||||
p.Logger().Err(err).Msg("event error")
|
||||
},
|
||||
)
|
||||
eventQueue.Start(p.watcher.Events(t.Context()))
|
||||
@@ -136,7 +136,7 @@ func (p *Provider) Start(parent task.Parent) gperr.Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Provider) LoadRoutes() (err gperr.Error) {
|
||||
func (p *Provider) LoadRoutes() (err error) {
|
||||
p.routes, err = p.loadRoutes()
|
||||
return err
|
||||
}
|
||||
@@ -188,7 +188,7 @@ func (p *Provider) GetRoute(alias string) (types.Route, bool) {
|
||||
return r.Impl(), true
|
||||
}
|
||||
|
||||
func (p *Provider) loadRoutes() (routes route.Routes, err gperr.Error) {
|
||||
func (p *Provider) loadRoutes() (routes route.Routes, err error) {
|
||||
routes, err = p.loadRoutesImpl()
|
||||
if err != nil && len(routes) == 0 {
|
||||
return route.Routes{}, err
|
||||
@@ -201,7 +201,7 @@ func (p *Provider) loadRoutes() (routes route.Routes, err gperr.Error) {
|
||||
r.Alias = alias
|
||||
r.SetProvider(p)
|
||||
if err := r.Validate(); err != nil {
|
||||
errs.Add(err.Subject(alias))
|
||||
errs.AddSubject(err, alias)
|
||||
delete(routes, alias)
|
||||
continue
|
||||
}
|
||||
@@ -210,11 +210,11 @@ func (p *Provider) loadRoutes() (routes route.Routes, err gperr.Error) {
|
||||
return routes, errs.Error()
|
||||
}
|
||||
|
||||
func (p *Provider) startRoute(parent task.Parent, r *route.Route) gperr.Error {
|
||||
func (p *Provider) startRoute(parent task.Parent, r *route.Route) error {
|
||||
err := r.Start(parent)
|
||||
if err != nil {
|
||||
p.lockDeleteRoute(r.Alias)
|
||||
return err.Subject(r.Alias)
|
||||
return gperr.PrependSubject(err, r.Alias)
|
||||
}
|
||||
|
||||
p.lockAddRoute(r)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/yusing/godoxy/agent/pkg/agent"
|
||||
"github.com/yusing/godoxy/agent/pkg/agentproxy"
|
||||
entrypoint "github.com/yusing/godoxy/internal/entrypoint/types"
|
||||
@@ -16,7 +18,6 @@ import (
|
||||
nettypes "github.com/yusing/godoxy/internal/net/types"
|
||||
route "github.com/yusing/godoxy/internal/route/types"
|
||||
"github.com/yusing/godoxy/internal/types"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
"github.com/yusing/goutils/http/reverseproxy"
|
||||
"github.com/yusing/goutils/task"
|
||||
"github.com/yusing/goutils/version"
|
||||
@@ -34,7 +35,7 @@ var _ types.ReverseProxyRoute = (*ReveseProxyRoute)(nil)
|
||||
|
||||
// var globalMux = http.NewServeMux() // TODO: support regex subdomain matching.
|
||||
|
||||
func NewReverseProxyRoute(base *Route) (*ReveseProxyRoute, gperr.Error) {
|
||||
func NewReverseProxyRoute(base *Route) (*ReveseProxyRoute, error) {
|
||||
httpConfig := base.HTTPConfig
|
||||
proxyURL := base.ProxyURL
|
||||
|
||||
@@ -123,7 +124,7 @@ func (r *ReveseProxyRoute) ReverseProxy() *reverseproxy.ReverseProxy {
|
||||
}
|
||||
|
||||
// Start implements task.TaskStarter.
|
||||
func (r *ReveseProxyRoute) Start(parent task.Parent) gperr.Error {
|
||||
func (r *ReveseProxyRoute) Start(parent task.Parent) error {
|
||||
r.task = parent.Subtask("http."+r.Name(), false)
|
||||
|
||||
switch {
|
||||
@@ -131,7 +132,7 @@ func (r *ReveseProxyRoute) Start(parent task.Parent) gperr.Error {
|
||||
waker, err := idlewatcher.NewWatcher(parent, r, r.IdlewatcherConfig())
|
||||
if err != nil {
|
||||
r.task.Finish(err)
|
||||
return gperr.Wrap(err)
|
||||
return err
|
||||
}
|
||||
r.handler = waker
|
||||
r.HealthMon = waker
|
||||
@@ -148,7 +149,7 @@ func (r *ReveseProxyRoute) Start(parent task.Parent) gperr.Error {
|
||||
r.rp.AccessLogger, err = accesslog.NewAccessLogger(r.task, r.AccessLog)
|
||||
if err != nil {
|
||||
r.task.Finish(err)
|
||||
return gperr.Wrap(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,14 +159,14 @@ func (r *ReveseProxyRoute) Start(parent task.Parent) gperr.Error {
|
||||
|
||||
if r.HealthMon != nil {
|
||||
if err := r.HealthMon.Start(r.task); err != nil {
|
||||
gperr.LogWarn("health monitor error", err, &r.rp.Logger)
|
||||
log.Warn().Err(err).Msg("health monitor error")
|
||||
r.HealthMon = nil
|
||||
}
|
||||
}
|
||||
|
||||
ep := entrypoint.FromCtx(parent.Context())
|
||||
if ep == nil {
|
||||
err := gperr.New("entrypoint not initialized")
|
||||
err := errors.New("entrypoint not initialized")
|
||||
r.task.Finish(err)
|
||||
return err
|
||||
}
|
||||
@@ -173,12 +174,12 @@ func (r *ReveseProxyRoute) Start(parent task.Parent) gperr.Error {
|
||||
if r.UseLoadBalance() {
|
||||
if err := r.addToLoadBalancer(parent, ep); err != nil {
|
||||
r.task.Finish(err)
|
||||
return gperr.Wrap(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := ep.StartAddRoute(r); err != nil {
|
||||
r.task.Finish(err)
|
||||
return gperr.Wrap(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -108,17 +108,17 @@ type (
|
||||
)
|
||||
|
||||
type lockedError struct {
|
||||
err gperr.Error
|
||||
err error
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
func (le *lockedError) Get() gperr.Error {
|
||||
func (le *lockedError) Get() error {
|
||||
le.lock.Lock()
|
||||
defer le.lock.Unlock()
|
||||
return le.err
|
||||
}
|
||||
|
||||
func (le *lockedError) Set(err gperr.Error) {
|
||||
func (le *lockedError) Set(err error) {
|
||||
le.lock.Lock()
|
||||
defer le.lock.Unlock()
|
||||
le.err = err
|
||||
@@ -131,7 +131,7 @@ func (r Routes) Contains(alias string) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
func (r *Route) Validate() gperr.Error {
|
||||
func (r *Route) Validate() error {
|
||||
// wait for alias to be set
|
||||
if r.Alias == "" {
|
||||
return nil
|
||||
@@ -150,13 +150,13 @@ func (r *Route) Validate() gperr.Error {
|
||||
return r.valErr.Get()
|
||||
}
|
||||
|
||||
func (r *Route) validate() gperr.Error {
|
||||
func (r *Route) validate() error {
|
||||
// if strings.HasPrefix(r.Alias, "godoxy") {
|
||||
// log.Debug().Any("route", r).Msg("validating route")
|
||||
// }
|
||||
if r.Agent != "" {
|
||||
if r.Container != nil {
|
||||
return gperr.Errorf("specifying agent is not allowed for docker container routes")
|
||||
return errors.New("specifying agent is not allowed for docker container routes")
|
||||
}
|
||||
var ok bool
|
||||
// by agent address
|
||||
@@ -165,7 +165,7 @@ func (r *Route) validate() gperr.Error {
|
||||
// fallback to get agent by name
|
||||
r.agent, ok = agentpool.GetAgent(r.Agent)
|
||||
if !ok {
|
||||
return gperr.Errorf("agent %s not found", r.Agent)
|
||||
return fmt.Errorf("agent %s not found", r.Agent)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -258,7 +258,7 @@ func (r *Route) validate() gperr.Error {
|
||||
switch r.Port.Proxy {
|
||||
case common.ProxyHTTPPort, common.ProxyHTTPSPort, common.APIHTTPPort:
|
||||
if r.Scheme.IsReverseProxy() || r.Scheme == route.SchemeTCP {
|
||||
return gperr.Errorf("localhost:%d is reserved for godoxy", r.Port.Proxy)
|
||||
return fmt.Errorf("localhost:%d is reserved for godoxy", r.Port.Proxy)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,9 +269,6 @@ func (r *Route) validate() gperr.Error {
|
||||
errs.Add(err)
|
||||
}
|
||||
|
||||
var impl types.Route
|
||||
var err gperr.Error
|
||||
|
||||
if r.ShouldExclude() {
|
||||
r.ProxyURL = gperr.Collect(&errs, nettypes.ParseURL, fmt.Sprintf("%s://%s", r.Scheme, net.JoinHostPort(r.Host, strconv.Itoa(r.Port.Proxy))))
|
||||
} else {
|
||||
@@ -318,6 +315,8 @@ func (r *Route) validate() gperr.Error {
|
||||
return errs.Error()
|
||||
}
|
||||
|
||||
var impl types.Route
|
||||
var err error
|
||||
switch r.Scheme {
|
||||
case route.SchemeFileServer:
|
||||
impl, err = NewFileServer(r)
|
||||
@@ -479,16 +478,16 @@ func (r *Route) Task() *task.Task {
|
||||
return r.task
|
||||
}
|
||||
|
||||
func (r *Route) Start(parent task.Parent) gperr.Error {
|
||||
func (r *Route) Start(parent task.Parent) error {
|
||||
r.onceStart.Do(func() {
|
||||
r.startErr.Set(r.start(parent))
|
||||
})
|
||||
return r.startErr.Get()
|
||||
}
|
||||
|
||||
func (r *Route) start(parent task.Parent) gperr.Error {
|
||||
func (r *Route) start(parent task.Parent) error {
|
||||
if r.impl == nil { // should not happen
|
||||
return gperr.New("route not initialized")
|
||||
return errors.New("route not initialized")
|
||||
}
|
||||
defer close(r.started)
|
||||
|
||||
@@ -511,7 +510,7 @@ func (r *Route) start(parent task.Parent) gperr.Error {
|
||||
} else {
|
||||
ep := entrypoint.FromCtx(parent.Context())
|
||||
if ep == nil {
|
||||
return gperr.New("entrypoint not initialized")
|
||||
return errors.New("entrypoint not initialized")
|
||||
}
|
||||
|
||||
r.task = parent.Subtask("excluded."+r.Name(), false)
|
||||
|
||||
@@ -72,7 +72,7 @@ var commands = map[string]struct {
|
||||
description: makeLines("Require HTTP authentication for incoming requests"),
|
||||
args: map[string]string{},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
if len(args) != 0 {
|
||||
return nil, ErrExpectNoArg
|
||||
}
|
||||
@@ -103,17 +103,17 @@ var commands = map[string]struct {
|
||||
"to": "the path to rewrite to, must start with /",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
if len(args) != 2 {
|
||||
return nil, ErrExpectTwoArgs
|
||||
}
|
||||
path1, err1 := validateURLPath(args[:1])
|
||||
path2, err2 := validateURLPath(args[1:])
|
||||
if err1 != nil {
|
||||
err1 = gperr.Errorf("from: %w", err1)
|
||||
err1 = gperr.PrependSubject(err1, "from")
|
||||
}
|
||||
if err2 != nil {
|
||||
err2 = gperr.Errorf("to: %w", err2)
|
||||
err2 = gperr.PrependSubject(err2, "to")
|
||||
}
|
||||
if err1 != nil || err2 != nil {
|
||||
return nil, gperr.Join(err1, err2)
|
||||
@@ -189,7 +189,7 @@ var commands = map[string]struct {
|
||||
"route": "the route to route to",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
@@ -227,7 +227,7 @@ var commands = map[string]struct {
|
||||
"text": "the error message to return",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
if len(args) != 2 {
|
||||
return nil, ErrExpectTwoArgs
|
||||
}
|
||||
@@ -267,7 +267,7 @@ var commands = map[string]struct {
|
||||
"realm": "the authentication realm",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
if len(args) == 1 {
|
||||
return args[0], nil
|
||||
}
|
||||
@@ -334,7 +334,7 @@ var commands = map[string]struct {
|
||||
"value": "the value to set",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
return validateModField(ModFieldSet, args)
|
||||
},
|
||||
build: func(args any) CommandHandler {
|
||||
@@ -354,7 +354,7 @@ var commands = map[string]struct {
|
||||
"value": "the value to add",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
return validateModField(ModFieldAdd, args)
|
||||
},
|
||||
build: func(args any) CommandHandler {
|
||||
@@ -373,7 +373,7 @@ var commands = map[string]struct {
|
||||
"field": "the field to remove",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
return validateModField(ModFieldRemove, args)
|
||||
},
|
||||
build: func(args any) CommandHandler {
|
||||
@@ -398,7 +398,7 @@ var commands = map[string]struct {
|
||||
"template": "the template to log",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
if len(args) != 3 {
|
||||
return nil, ErrExpectThreeArgs
|
||||
}
|
||||
@@ -455,7 +455,7 @@ var commands = map[string]struct {
|
||||
"body": "the body of the notification",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
if len(args) != 4 {
|
||||
return nil, ErrExpectFourArgs
|
||||
}
|
||||
@@ -543,7 +543,7 @@ func (cmd *Command) Parse(v string) error {
|
||||
validArgs, err := builder.validate(args)
|
||||
if err != nil {
|
||||
// Only attach help for the directive that failed, avoid bringing in unrelated KV errors
|
||||
return err.Subject(directive).With(builder.help.Error())
|
||||
return gperr.PrependSubject(err, directive).With(builder.help.Error())
|
||||
}
|
||||
|
||||
handler := builder.build(validArgs)
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/yusing/godoxy/internal/serialization"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
)
|
||||
|
||||
// mockUpstream creates a simple upstream handler for testing
|
||||
@@ -32,7 +31,7 @@ func mockUpstreamWithHeaders(status int, body string, headers http.Header) http.
|
||||
}
|
||||
}
|
||||
|
||||
func parseRules(data string, target *Rules) gperr.Error {
|
||||
func parseRules(data string, target *Rules) error {
|
||||
_, err := serialization.ConvertString(data, reflect.ValueOf(target))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
httputils "github.com/yusing/goutils/http"
|
||||
ioutils "github.com/yusing/goutils/io"
|
||||
)
|
||||
@@ -228,7 +227,7 @@ var modFields = map[string]struct {
|
||||
"template": "the body template",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
@@ -273,7 +272,7 @@ var modFields = map[string]struct {
|
||||
"template": "the response body template",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
@@ -301,7 +300,7 @@ var modFields = map[string]struct {
|
||||
"code": "the status code",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package rules
|
||||
import (
|
||||
"testing"
|
||||
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func TestErrorFormat(t *testing.T) {
|
||||
@@ -19,5 +19,5 @@ func TestErrorFormat(t *testing.T) {
|
||||
do: set invalid_command
|
||||
- do: set resp_body "{{ .Request.Method {{ .Request.URL.Path }}"
|
||||
`, &rules)
|
||||
gperr.LogError("error", err)
|
||||
log.Err(err).Msg("error")
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ Generate help string as error, e.g.
|
||||
from: the path to rewrite, must start with /
|
||||
to: the path to rewrite to, must start with /
|
||||
*/
|
||||
func (h *Help) Error() gperr.Error {
|
||||
func (h *Help) Error() error {
|
||||
var lines gperr.MultilineError
|
||||
|
||||
lines.Adds(ansi.WithANSI(h.command, ansi.HighlightGreen))
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/yusing/godoxy/internal/route"
|
||||
"github.com/yusing/godoxy/internal/route/routes"
|
||||
"github.com/yusing/godoxy/internal/serialization"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
. "github.com/yusing/godoxy/internal/route/rules"
|
||||
@@ -44,7 +43,7 @@ func mockRoute(alias string) *route.FileServer {
|
||||
return &route.FileServer{Route: &route.Route{Alias: alias}}
|
||||
}
|
||||
|
||||
func parseRules(data string, target *Rules) gperr.Error {
|
||||
func parseRules(data string, target *Rules) error {
|
||||
_, err := serialization.ConvertString(strings.TrimSpace(data), reflect.ValueOf(target))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
|
||||
"github.com/yusing/godoxy/internal/common"
|
||||
"github.com/yusing/godoxy/internal/logging/accesslog"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
)
|
||||
|
||||
type noopWriteCloser struct {
|
||||
@@ -31,7 +30,7 @@ var (
|
||||
testFilesLock sync.Mutex
|
||||
)
|
||||
|
||||
func openFile(path string) (io.WriteCloser, gperr.Error) {
|
||||
func openFile(path string) (io.WriteCloser, error) {
|
||||
switch path {
|
||||
case "/dev/stdout":
|
||||
return stdout, nil
|
||||
|
||||
@@ -59,7 +59,7 @@ var checkers = map[string]struct {
|
||||
),
|
||||
args: map[string]string{},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
if len(args) != 0 {
|
||||
return nil, ErrExpectNoArg
|
||||
}
|
||||
@@ -251,7 +251,7 @@ var checkers = map[string]struct {
|
||||
"proto": "the http protocol (http, https, h3)",
|
||||
},
|
||||
},
|
||||
validate: func(args []string) (any, gperr.Error) {
|
||||
validate: func(args []string) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
@@ -581,7 +581,7 @@ func (on *RuleOn) Parse(v string) error {
|
||||
}
|
||||
parsed, isResp, err := parseOn(rule)
|
||||
if err != nil {
|
||||
errs.Add(err.Subjectf("line %d", i+1))
|
||||
errs.AddSubjectf(err, "line %d", i+1)
|
||||
continue
|
||||
}
|
||||
if isResp {
|
||||
@@ -603,7 +603,7 @@ func (on *RuleOn) MarshalText() ([]byte, error) {
|
||||
return []byte(on.String()), nil
|
||||
}
|
||||
|
||||
func parseOn(line string) (Checker, bool, gperr.Error) {
|
||||
func parseOn(line string) (Checker, bool, error) {
|
||||
ors := splitPipe(line)
|
||||
|
||||
if len(ors) > 1 {
|
||||
@@ -645,7 +645,7 @@ func parseOn(line string) (Checker, bool, gperr.Error) {
|
||||
|
||||
validArgs, err := checker.validate(args)
|
||||
if err != nil {
|
||||
return nil, false, err.With(checker.help.Error())
|
||||
return nil, false, gperr.Wrap(err).With(checker.help.Error())
|
||||
}
|
||||
|
||||
checkFunc := checker.builder(validArgs)
|
||||
|
||||
@@ -31,7 +31,7 @@ var quoteChars = [256]bool{
|
||||
// error 403 "Forbidden 'foo' 'bar'"
|
||||
// error 403 Forbidden\ \"foo\"\ \"bar\".
|
||||
// error 403 "Message: ${CLOUDFLARE_API_KEY}"
|
||||
func parse(v string) (subject string, args []string, err gperr.Error) {
|
||||
func parse(v string) (subject string, args []string, err error) {
|
||||
buf := bytes.NewBuffer(make([]byte, 0, len(v)))
|
||||
|
||||
escaped := false
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/yusing/godoxy/internal/route/rules"
|
||||
"github.com/yusing/godoxy/internal/serialization"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
)
|
||||
|
||||
//go:embed *.yml
|
||||
@@ -35,12 +34,12 @@ func initPresets() {
|
||||
var rules rules.Rules
|
||||
content, err := fs.ReadFile(file.Name())
|
||||
if err != nil {
|
||||
gperr.LogError("failed to read rule preset", err)
|
||||
log.Err(err).Msg("failed to read rule preset")
|
||||
continue
|
||||
}
|
||||
_, err = serialization.ConvertString(string(content), reflect.ValueOf(&rules))
|
||||
if err != nil {
|
||||
gperr.LogError("failed to unmarshal rule preset", err)
|
||||
log.Err(err).Msg("failed to unmarshal rule preset")
|
||||
continue
|
||||
}
|
||||
rulePresets[file.Name()] = rules
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
"github.com/quic-go/quic-go/http3"
|
||||
"github.com/rs/zerolog/log"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
httputils "github.com/yusing/goutils/http"
|
||||
"golang.org/x/net/http2"
|
||||
|
||||
@@ -58,7 +57,7 @@ func (rule *Rule) IsResponseRule() bool {
|
||||
return rule.On.IsResponseChecker() || rule.Do.IsResponseHandler()
|
||||
}
|
||||
|
||||
func (rules Rules) Validate() gperr.Error {
|
||||
func (rules Rules) Validate() error {
|
||||
var defaultRulesFound []int
|
||||
for i, rule := range rules {
|
||||
if rule.Name == "default" || rule.On.raw == OnDefault {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
ValidateFunc func(args []string) (any, gperr.Error)
|
||||
ValidateFunc func(args []string) (any, error)
|
||||
Tuple[T1, T2 any] struct {
|
||||
First T1
|
||||
Second T2
|
||||
@@ -62,7 +62,7 @@ func (t *Tuple4[T1, T2, T3, T4]) String() string {
|
||||
}
|
||||
|
||||
// validateSingleMatcher returns Matcher with the matcher validated.
|
||||
func validateSingleMatcher(args []string) (any, gperr.Error) {
|
||||
func validateSingleMatcher(args []string) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func validateSingleMatcher(args []string) (any, gperr.Error) {
|
||||
}
|
||||
|
||||
// toKVOptionalVMatcher returns *MapValueMatcher that value is optional.
|
||||
func toKVOptionalVMatcher(args []string) (any, gperr.Error) {
|
||||
func toKVOptionalVMatcher(args []string) (any, error) {
|
||||
switch len(args) {
|
||||
case 1:
|
||||
return &MapValueMatcher{args[0], nil}, nil
|
||||
@@ -85,7 +85,7 @@ func toKVOptionalVMatcher(args []string) (any, gperr.Error) {
|
||||
}
|
||||
}
|
||||
|
||||
func toKeyValueTemplate(args []string) (any, gperr.Error) {
|
||||
func toKeyValueTemplate(args []string) (any, error) {
|
||||
if len(args) != 2 {
|
||||
return nil, ErrExpectTwoArgs
|
||||
}
|
||||
@@ -98,7 +98,7 @@ func toKeyValueTemplate(args []string) (any, gperr.Error) {
|
||||
}
|
||||
|
||||
// validateURL returns types.URL with the URL validated.
|
||||
func validateURL(args []string) (any, gperr.Error) {
|
||||
func validateURL(args []string) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func validateURL(args []string) (any, gperr.Error) {
|
||||
}
|
||||
|
||||
// validateCIDR returns types.CIDR with the CIDR validated.
|
||||
func validateCIDR(args []string) (any, gperr.Error) {
|
||||
func validateCIDR(args []string) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
@@ -131,7 +131,7 @@ func validateCIDR(args []string) (any, gperr.Error) {
|
||||
}
|
||||
|
||||
// validateURLPath returns string with the path validated.
|
||||
func validateURLPath(args []string) (any, gperr.Error) {
|
||||
func validateURLPath(args []string) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
@@ -148,7 +148,7 @@ func validateURLPath(args []string) (any, gperr.Error) {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func validateURLPathMatcher(args []string) (any, gperr.Error) {
|
||||
func validateURLPathMatcher(args []string) (any, error) {
|
||||
path, err := validateURLPath(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -157,7 +157,7 @@ func validateURLPathMatcher(args []string) (any, gperr.Error) {
|
||||
}
|
||||
|
||||
// validateFSPath returns string with the path validated.
|
||||
func validateFSPath(args []string) (any, gperr.Error) {
|
||||
func validateFSPath(args []string) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
@@ -169,7 +169,7 @@ func validateFSPath(args []string) (any, gperr.Error) {
|
||||
}
|
||||
|
||||
// validateMethod returns string with the method validated.
|
||||
func validateMethod(args []string) (any, gperr.Error) {
|
||||
func validateMethod(args []string) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
@@ -200,7 +200,7 @@ func validateStatusCode(status string) (int, error) {
|
||||
// - 3xx
|
||||
// - 4xx
|
||||
// - 5xx
|
||||
func validateStatusRange(args []string) (any, gperr.Error) {
|
||||
func validateStatusRange(args []string) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, ErrExpectOneArg
|
||||
}
|
||||
@@ -232,7 +232,7 @@ func validateStatusRange(args []string) (any, gperr.Error) {
|
||||
}
|
||||
|
||||
// validateUserBCryptPassword returns *HashedCrendential with the password validated.
|
||||
func validateUserBCryptPassword(args []string) (any, gperr.Error) {
|
||||
func validateUserBCryptPassword(args []string) (any, error) {
|
||||
if len(args) != 2 {
|
||||
return nil, ErrExpectTwoArgs
|
||||
}
|
||||
@@ -240,7 +240,7 @@ func validateUserBCryptPassword(args []string) (any, gperr.Error) {
|
||||
}
|
||||
|
||||
// validateModField returns CommandHandler with the field validated.
|
||||
func validateModField(mod FieldModifier, args []string) (CommandHandler, gperr.Error) {
|
||||
func validateModField(mod FieldModifier, args []string) (CommandHandler, error) {
|
||||
if len(args) == 0 {
|
||||
return nil, ErrExpectTwoOrThreeArgs
|
||||
}
|
||||
@@ -257,7 +257,7 @@ func validateModField(mod FieldModifier, args []string) (CommandHandler, gperr.E
|
||||
}
|
||||
validArgs, err := setField.validate(args[1:])
|
||||
if err != nil {
|
||||
return nil, err.With(setField.help.Error())
|
||||
return nil, gperr.Wrap(err).With(setField.help.Error())
|
||||
}
|
||||
modder := setField.builder(validArgs)
|
||||
switch mod {
|
||||
@@ -281,7 +281,7 @@ func validateModField(mod FieldModifier, args []string) (CommandHandler, gperr.E
|
||||
return set, nil
|
||||
}
|
||||
|
||||
func validateTemplate(tmplStr string, newline bool) (templateString, gperr.Error) {
|
||||
func validateTemplate(tmplStr string, newline bool) (templateString, error) {
|
||||
if newline && !strings.HasSuffix(tmplStr, "\n") {
|
||||
tmplStr += "\n"
|
||||
}
|
||||
@@ -292,22 +292,15 @@ func validateTemplate(tmplStr string, newline bool) (templateString, gperr.Error
|
||||
|
||||
err := ValidateVars(tmplStr)
|
||||
if err != nil {
|
||||
return templateString{}, gperr.Wrap(err)
|
||||
return templateString{}, err
|
||||
}
|
||||
return templateString{tmplStr, true}, nil
|
||||
}
|
||||
|
||||
func validateLevel(level string) (zerolog.Level, gperr.Error) {
|
||||
func validateLevel(level string) (zerolog.Level, error) {
|
||||
l, err := zerolog.ParseLevel(level)
|
||||
if err != nil {
|
||||
return zerolog.NoLevel, ErrInvalidArguments.With(err)
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// func validateNotifProvider(provider string) gperr.Error {
|
||||
// if !notif.HasProvider(provider) {
|
||||
// return ErrInvalidArguments.Subject(provider)
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
@@ -2,17 +2,18 @@ package route
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
entrypoint "github.com/yusing/godoxy/internal/entrypoint/types"
|
||||
"github.com/yusing/godoxy/internal/health/monitor"
|
||||
"github.com/yusing/godoxy/internal/idlewatcher"
|
||||
nettypes "github.com/yusing/godoxy/internal/net/types"
|
||||
"github.com/yusing/godoxy/internal/route/stream"
|
||||
"github.com/yusing/godoxy/internal/types"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
"github.com/yusing/goutils/task"
|
||||
)
|
||||
|
||||
@@ -24,7 +25,7 @@ type StreamRoute struct {
|
||||
|
||||
var _ types.StreamRoute = (*StreamRoute)(nil)
|
||||
|
||||
func NewStreamRoute(base *Route) (types.Route, gperr.Error) {
|
||||
func NewStreamRoute(base *Route) (types.Route, error) {
|
||||
// TODO: support non-coherent scheme
|
||||
return &StreamRoute{Route: base}, nil
|
||||
}
|
||||
@@ -34,14 +35,14 @@ func (r *StreamRoute) Stream() nettypes.Stream {
|
||||
}
|
||||
|
||||
// Start implements task.TaskStarter.
|
||||
func (r *StreamRoute) Start(parent task.Parent) gperr.Error {
|
||||
func (r *StreamRoute) Start(parent task.Parent) error {
|
||||
if r.LisURL == nil {
|
||||
return gperr.Errorf("listen URL is not set")
|
||||
return errors.New("listen URL is not set")
|
||||
}
|
||||
|
||||
stream, err := r.initStream()
|
||||
if err != nil {
|
||||
return gperr.Wrap(err)
|
||||
return err
|
||||
}
|
||||
r.stream = stream
|
||||
|
||||
@@ -52,7 +53,7 @@ func (r *StreamRoute) Start(parent task.Parent) gperr.Error {
|
||||
waker, err := idlewatcher.NewWatcher(parent, r, r.IdlewatcherConfig())
|
||||
if err != nil {
|
||||
r.task.Finish(err)
|
||||
return gperr.Wrap(err, "idlewatcher error")
|
||||
return fmt.Errorf("idlewatcher error: %w", err)
|
||||
}
|
||||
r.stream = waker
|
||||
r.HealthMon = waker
|
||||
@@ -62,20 +63,20 @@ func (r *StreamRoute) Start(parent task.Parent) gperr.Error {
|
||||
|
||||
if r.HealthMon != nil {
|
||||
if err := r.HealthMon.Start(r.task); err != nil {
|
||||
gperr.LogWarn("health monitor error", err)
|
||||
log.Warn().Err(err).Msg("health monitor error")
|
||||
r.HealthMon = nil
|
||||
}
|
||||
}
|
||||
|
||||
ep := entrypoint.FromCtx(parent.Context())
|
||||
if ep == nil {
|
||||
err := gperr.New("entrypoint not initialized")
|
||||
err := errors.New("entrypoint not initialized")
|
||||
r.task.Finish(err)
|
||||
return err
|
||||
}
|
||||
if err := ep.StartAddRoute(r); err != nil {
|
||||
r.task.Finish(err)
|
||||
return gperr.Wrap(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package route
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -25,7 +26,7 @@ type HTTPConfig struct {
|
||||
}
|
||||
|
||||
// BuildTLSConfig creates a TLS configuration based on the HTTP config options.
|
||||
func (cfg *HTTPConfig) BuildTLSConfig(targetURL *url.URL) (*tls.Config, gperr.Error) {
|
||||
func (cfg *HTTPConfig) BuildTLSConfig(targetURL *url.URL) (*tls.Config, error) {
|
||||
tlsConfig := &tls.Config{}
|
||||
|
||||
// Handle InsecureSkipVerify (legacy NoTLSVerify option)
|
||||
@@ -54,15 +55,12 @@ func (cfg *HTTPConfig) BuildTLSConfig(targetURL *url.URL) (*tls.Config, gperr.Er
|
||||
if cfg.SSLTrustedCertificate != "" {
|
||||
caCertData, err := os.ReadFile(cfg.SSLTrustedCertificate)
|
||||
if err != nil {
|
||||
return nil, gperr.New("failed to read trusted certificate file").
|
||||
Subject(cfg.SSLTrustedCertificate).
|
||||
With(err)
|
||||
return nil, gperr.PrependSubject(err, cfg.SSLTrustedCertificate)
|
||||
}
|
||||
|
||||
caCertPool := x509.NewCertPool()
|
||||
if !caCertPool.AppendCertsFromPEM(caCertData) {
|
||||
return nil, gperr.New("failed to parse trusted certificates").
|
||||
Subject(cfg.SSLTrustedCertificate)
|
||||
return nil, gperr.PrependSubject(errors.New("failed to parse trusted certificates"), cfg.SSLTrustedCertificate)
|
||||
}
|
||||
tlsConfig.RootCAs = caCertPool
|
||||
}
|
||||
@@ -70,16 +68,16 @@ func (cfg *HTTPConfig) BuildTLSConfig(targetURL *url.URL) (*tls.Config, gperr.Er
|
||||
// Handle ssl_certificate and ssl_certificate_key (client certificates)
|
||||
if cfg.SSLCertificate != "" {
|
||||
if cfg.SSLCertificateKey == "" {
|
||||
return nil, gperr.New("ssl_certificate_key is required when ssl_certificate is specified")
|
||||
return nil, errors.New("ssl_certificate_key is required when ssl_certificate is specified")
|
||||
}
|
||||
|
||||
clientCert, err := tls.LoadX509KeyPair(cfg.SSLCertificate, cfg.SSLCertificateKey)
|
||||
if err != nil {
|
||||
return nil, gperr.New("failed to load client certificate").
|
||||
Subject(cfg.SSLCertificate).
|
||||
With(err)
|
||||
return nil, gperr.PrependSubject(err, cfg.SSLCertificate)
|
||||
}
|
||||
tlsConfig.Certificates = []tls.Certificate{clientCert}
|
||||
} else if cfg.SSLCertificateKey != "" {
|
||||
return nil, errors.New("ssl_certificate is required when ssl_certificate_key is specified")
|
||||
}
|
||||
|
||||
// Handle ssl_protocols (TLS versions)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
@@ -13,8 +14,8 @@ type Port struct {
|
||||
} // @name Port
|
||||
|
||||
var (
|
||||
ErrInvalidPortSyntax = gperr.New("invalid port syntax, expect [listening_port:]target_port")
|
||||
ErrPortOutOfRange = gperr.New("port out of range")
|
||||
ErrInvalidPortSyntax = errors.New("invalid port syntax, expect [listening_port:]target_port")
|
||||
ErrPortOutOfRange = errors.New("port out of range")
|
||||
)
|
||||
|
||||
// Parse implements strutils.Parser.
|
||||
@@ -30,7 +31,7 @@ func (p *Port) Parse(v string) (err error) {
|
||||
p.Proxy, err2 = strconv.Atoi(parts[1])
|
||||
err = gperr.Join(err, err2)
|
||||
default:
|
||||
return ErrInvalidPortSyntax.Subject(v)
|
||||
return gperr.PrependSubject(ErrInvalidPortSyntax, v)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -38,11 +39,11 @@ func (p *Port) Parse(v string) (err error) {
|
||||
}
|
||||
|
||||
if p.Listening < MinPort || p.Listening > MaxPort {
|
||||
return ErrPortOutOfRange.Subjectf("%d", p.Listening)
|
||||
return gperr.PrependSubject(ErrPortOutOfRange, strconv.Itoa(p.Listening))
|
||||
}
|
||||
|
||||
if p.Proxy < MinPort || p.Proxy > MaxPort {
|
||||
return ErrPortOutOfRange.Subjectf("%d", p.Proxy)
|
||||
return gperr.PrependSubject(ErrPortOutOfRange, strconv.Itoa(p.Proxy))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
@@ -9,7 +10,7 @@ import (
|
||||
|
||||
type Scheme uint8
|
||||
|
||||
var ErrInvalidScheme = gperr.New("invalid scheme")
|
||||
var ErrInvalidScheme = errors.New("invalid scheme")
|
||||
|
||||
const (
|
||||
SchemeHTTP Scheme = 1 << iota
|
||||
@@ -79,7 +80,7 @@ func (s *Scheme) Parse(v string) error {
|
||||
case schemeStrFileServer:
|
||||
*s = SchemeFileServer
|
||||
default:
|
||||
return ErrInvalidScheme.Subject(v)
|
||||
return gperr.PrependSubject(ErrInvalidScheme, v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user