From df3212873fe58026b0fef0e2fb46e52eaa4358e4 Mon Sep 17 00:00:00 2001 From: yusing Date: Thu, 6 Feb 2025 17:54:30 +0800 Subject: [PATCH] updated route JSONMarshalling --- internal/route/provider/docker.go | 6 ++++-- internal/route/reverse_proxy.go | 6 +++--- internal/route/route.go | 21 +++++++++++++-------- internal/route/stream_impl.go | 8 ++++---- internal/utils/serialization.go | 16 +++++++++++++--- 5 files changed, 37 insertions(+), 20 deletions(-) diff --git a/internal/route/provider/docker.go b/internal/route/provider/docker.go index 8299bb6..37a96c4 100755 --- a/internal/route/provider/docker.go +++ b/internal/route/provider/docker.go @@ -102,7 +102,8 @@ func (p *DockerProvider) routesFromContainerLabels(container *docker.Container) // init entries map for all aliases for _, a := range container.Aliases { - routes[a] = &route.Route{Container: container} + routes[a] = &route.Route{} + routes[a].Metadata.Container = container } errs := E.NewBuilder("label errors") @@ -156,7 +157,8 @@ func (p *DockerProvider) routesFromContainerLabels(container *docker.Container) // init entry if not exist r, ok := routes[alias] if !ok { - r = &route.Route{Container: container} + r = &route.Route{} + r.Metadata.Container = container routes[alias] = r } diff --git a/internal/route/reverse_proxy.go b/internal/route/reverse_proxy.go index a0b02ee..a80b94b 100755 --- a/internal/route/reverse_proxy.go +++ b/internal/route/reverse_proxy.go @@ -51,7 +51,7 @@ func NewReverseProxyRoute(base *Route) (*ReveseProxyRoute, E.Error) { } service := base.TargetName() - rp := reverseproxy.NewReverseProxy(service, base.pURL, trans) + rp := reverseproxy.NewReverseProxy(service, base.ProxyURL, trans) if len(base.Middlewares) > 0 { err := middleware.PatchReverseProxy(rp, base.Middlewares) @@ -86,10 +86,10 @@ func (r *ReveseProxyRoute) Start(parent task.Parent) E.Error { r.HealthMon = waker case r.UseHealthCheck(): if r.IsDocker() { - client, err := docker.ConnectClient(r.idlewatcher.DockerHost) + client, err := docker.ConnectClient(r.Idlewatcher.DockerHost) if err == nil { fallback := monitor.NewHTTPHealthChecker(r.rp.TargetURL, r.HealthCheck) - r.HealthMon = monitor.NewDockerHealthMonitor(client, r.idlewatcher.ContainerID, r.TargetName(), r.HealthCheck, fallback) + r.HealthMon = monitor.NewDockerHealthMonitor(client, r.Idlewatcher.ContainerID, r.TargetName(), r.HealthCheck, fallback) r.task.OnCancel("close_docker_client", client.Close) } } diff --git a/internal/route/route.go b/internal/route/route.go index c55f94e..868e612 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -42,13 +42,18 @@ type ( Homepage *homepage.Item `json:"homepage,omitempty"` AccessLog *accesslog.Config `json:"access_log,omitempty"` + Metadata `deserialize:"-"` + } + + Metadata struct { /* Docker only */ Container *docker.Container `json:"container,omitempty"` Provider string `json:"provider,omitempty"` // private fields - lURL, pURL *net.URL // listening url and proxy url - idlewatcher *idlewatcher.Config + LisURL *net.URL `json:"lurl,omitempty"` + ProxyURL *net.URL `json:"purl,omitempty"` + Idlewatcher *idlewatcher.Config `json:"idlewatcher,omitempty"` impl types.Route isValidated bool @@ -79,7 +84,7 @@ func (r *Route) Validate() (err E.Error) { } fallthrough case types.SchemeTCP, types.SchemeUDP: - r.lURL = E.Collect(errs, net.ParseURL, fmt.Sprintf("%s://%s:%d", r.Scheme, r.Host, r.Port.Listening)) + r.LisURL = E.Collect(errs, net.ParseURL, fmt.Sprintf("%s://%s:%d", r.Scheme, r.Host, r.Port.Listening)) fallthrough default: if r.Port.Proxy == 0 && !r.IsDocker() { @@ -88,8 +93,8 @@ func (r *Route) Validate() (err E.Error) { if r.LoadBalance != nil && r.LoadBalance.Link == "" { r.LoadBalance = nil } - r.pURL = E.Collect(errs, net.ParseURL, fmt.Sprintf("%s://%s:%d", r.Scheme, r.Host, r.Port.Proxy)) - r.idlewatcher = E.Collect(errs, idlewatcher.ValidateConfig, r.Container) + r.ProxyURL = E.Collect(errs, net.ParseURL, fmt.Sprintf("%s://%s:%d", r.Scheme, r.Host, r.Port.Proxy)) + r.Idlewatcher = E.Collect(errs, idlewatcher.ValidateConfig, r.Container) } if !r.UseHealthCheck() && (r.UseLoadBalance() || r.UseIdleWatcher()) { @@ -142,7 +147,7 @@ func (r *Route) TargetName() string { } func (r *Route) TargetURL() *net.URL { - return r.pURL + return r.ProxyURL } func (r *Route) Type() types.RouteType { @@ -160,7 +165,7 @@ func (r *Route) HealthMonitor() health.HealthMonitor { } func (r *Route) IdlewatcherConfig() *idlewatcher.Config { - return r.idlewatcher + return r.Idlewatcher } func (r *Route) HealthCheckConfig() *health.HealthCheckConfig { @@ -223,7 +228,7 @@ func (r *Route) UseLoadBalance() bool { } func (r *Route) UseIdleWatcher() bool { - return r.idlewatcher != nil && r.idlewatcher.IdleTimeout > 0 + return r.Idlewatcher != nil && r.Idlewatcher.IdleTimeout > 0 } func (r *Route) UseHealthCheck() bool { diff --git a/internal/route/stream_impl.go b/internal/route/stream_impl.go index 263f12d..316f6db 100644 --- a/internal/route/stream_impl.go +++ b/internal/route/stream_impl.go @@ -46,11 +46,11 @@ func (stream *Stream) Setup() error { switch stream.Scheme { case "tcp": - stream.targetAddr, err = net.ResolveTCPAddr("tcp", stream.pURL.Host) + stream.targetAddr, err = net.ResolveTCPAddr("tcp", stream.ProxyURL.Host) if err != nil { return err } - tcpListener, err := lcfg.Listen(ctx, "tcp", stream.lURL.Host) + tcpListener, err := lcfg.Listen(ctx, "tcp", stream.LisURL.Host) if err != nil { return err } @@ -58,11 +58,11 @@ func (stream *Stream) Setup() error { stream.Port.Listening = tcpListener.Addr().(*net.TCPAddr).Port stream.listener = types.NetListener(tcpListener) case "udp": - stream.targetAddr, err = net.ResolveUDPAddr("udp", stream.pURL.Host) + stream.targetAddr, err = net.ResolveUDPAddr("udp", stream.ProxyURL.Host) if err != nil { return err } - udpListener, err := lcfg.ListenPacket(ctx, "udp", stream.lURL.Host) + udpListener, err := lcfg.ListenPacket(ctx, "udp", stream.LisURL.Host) if err != nil { return err } diff --git a/internal/utils/serialization.go b/internal/utils/serialization.go index 4b3c6af..6830efd 100644 --- a/internal/utils/serialization.go +++ b/internal/utils/serialization.go @@ -31,6 +31,13 @@ var ( ErrUnknownField = E.New("unknown field") ) +var ( + tagDeserialize = "deserialize" // `deserialize:"-"` to exclude from deserialization + tagJSON = "json" // share between Deserialize and json.Marshal + tagValidate = "validate" // uses go-playground/validator + tagAliases = "aliases" // declare aliases for fields +) + var mapUnmarshalerType = reflect.TypeFor[MapUnmarshaller]() var defaultValues = functional.NewMapOf[reflect.Type, func() any]() @@ -67,6 +74,9 @@ func extractFields(t reflect.Type) (all, anonymous []reflect.StructField) { if !field.IsExported() { continue } + if field.Tag.Get(tagDeserialize) == "-" { + continue + } if field.Anonymous { f1, f2 := extractFields(field.Type) fields = append(fields, f1...) @@ -213,7 +223,7 @@ func Deserialize(src SerializedObject, dst any) (err E.Error) { } for _, field := range fields { var key string - if jsonTag, ok := field.Tag.Lookup("json"); ok { + if jsonTag, ok := field.Tag.Lookup(tagJSON); ok { if jsonTag == "-" { continue } @@ -225,10 +235,10 @@ func Deserialize(src SerializedObject, dst any) (err E.Error) { mapping[key] = dstV.FieldByName(field.Name) if !hasValidateTag { - _, hasValidateTag = field.Tag.Lookup("validate") + _, hasValidateTag = field.Tag.Lookup(tagValidate) } - aliases, ok := field.Tag.Lookup("aliases") + aliases, ok := field.Tag.Lookup(tagAliases) if ok { for _, alias := range strutils.CommaSeperatedList(aliases) { mapping[alias] = dstV.FieldByName(field.Name)