diff --git a/internal/route/port_selection.go b/internal/route/port_selection.go new file mode 100644 index 00000000..a5676983 --- /dev/null +++ b/internal/route/port_selection.go @@ -0,0 +1,79 @@ +package route + +var ( + ImageNamePortMapTCP = map[string]int{ + "mssql": 1433, + "mysql": 3306, + "mariadb": 3306, + "postgres": 5432, + "rabbitmq": 5672, + "redis": 6379, + "memcached": 11211, + "mongo": 27017, + "minecraft-server": 25565, + } + + ImageNamePortMapHTTP = map[string]int{ + "adguardhome": 3000, + "bazarr": 6767, + "calibre-web": 8083, + "changedetection.io": 3000, + "dockge": 5001, + "gitea": 3000, + "gogs": 3000, + "grafana": 3000, + "home-assistant": 8123, + "homebridge": 8581, + "httpd": 80, + "immich": 3001, + "jellyfin": 8096, + "lidarr": 8686, + "microbin": 8080, + "nginx": 80, + "nginx-proxy-manager": 81, + "open-webui": 8080, + "plex": 32400, + "prometheus": 9090, + "prowlarr": 9696, + "radarr": 7878, + "radarr-sma": 7878, + "rsshub": 1200, + "rss-bridge": 80, + "sonarr": 8989, + "sonarr-sma": 8989, + "uptime-kuma": 3001, + "whisparr": 6969, + } + ImageNamePortMapHTTPS = map[string]int{ + "portainer-be": 9443, + "portainer-ce": 9443, + } + AliasPortMapHTTP = map[string]int{} + AliasPortMapHTTPS = map[string]int{ + "portainer": 9443, + "crafty": 8080, + } +) + +func getSchemePortByImageName(imageName string) (scheme string, port int, ok bool) { + if port, ok := ImageNamePortMapHTTP[imageName]; ok { + return "http", port, true + } + if port, ok := ImageNamePortMapHTTPS[imageName]; ok { + return "https", port, true + } + if port, ok := ImageNamePortMapTCP[imageName]; ok { + return "tcp", port, true + } + return +} + +func getSchemePortByAlias(alias string) (scheme string, port int, ok bool) { + if port, ok := AliasPortMapHTTP[alias]; ok { + return "http", port, true + } + if port, ok := AliasPortMapHTTPS[alias]; ok { + return "https", port, true + } + return +} diff --git a/internal/route/reverse_proxy.go b/internal/route/reverse_proxy.go index 9631f346..ee1e1ae5 100755 --- a/internal/route/reverse_proxy.go +++ b/internal/route/reverse_proxy.go @@ -1,21 +1,24 @@ package route import ( + "crypto/tls" "net/http" + "github.com/yusing/go-proxy/agent/pkg/agent" + "github.com/yusing/go-proxy/agent/pkg/agentproxy" "github.com/yusing/go-proxy/internal/api/v1/favicon" "github.com/yusing/go-proxy/internal/common" "github.com/yusing/go-proxy/internal/docker" "github.com/yusing/go-proxy/internal/docker/idlewatcher" "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/logging" - gphttp "github.com/yusing/go-proxy/internal/net/http" - "github.com/yusing/go-proxy/internal/net/http/accesslog" - "github.com/yusing/go-proxy/internal/net/http/loadbalancer" - loadbalance "github.com/yusing/go-proxy/internal/net/http/loadbalancer/types" - "github.com/yusing/go-proxy/internal/net/http/middleware" - metricslogger "github.com/yusing/go-proxy/internal/net/http/middleware/metrics_logger" - "github.com/yusing/go-proxy/internal/net/http/reverseproxy" + gphttp "github.com/yusing/go-proxy/internal/net/gphttp" + "github.com/yusing/go-proxy/internal/net/gphttp/accesslog" + "github.com/yusing/go-proxy/internal/net/gphttp/loadbalancer" + loadbalance "github.com/yusing/go-proxy/internal/net/gphttp/loadbalancer/types" + "github.com/yusing/go-proxy/internal/net/gphttp/middleware" + metricslogger "github.com/yusing/go-proxy/internal/net/gphttp/middleware/metrics_logger" + "github.com/yusing/go-proxy/internal/net/gphttp/reverseproxy" "github.com/yusing/go-proxy/internal/route/routes" "github.com/yusing/go-proxy/internal/task" "github.com/yusing/go-proxy/internal/watcher/health" @@ -40,17 +43,25 @@ type ( func NewReverseProxyRoute(base *Route) (*ReveseProxyRoute, gperr.Error) { httpConfig := base.HTTPConfig + proxyURL := base.ProxyURL - if httpConfig.NoTLSVerify { - trans = gphttp.DefaultTransportNoTLS - } - if httpConfig.ResponseHeaderTimeout > 0 { - trans = trans.Clone() - trans.ResponseHeaderTimeout = httpConfig.ResponseHeaderTimeout + var trans *http.Transport + a := base.Agent() + if a != nil { + trans = a.Transport() + proxyURL = agent.HTTPProxyURL + } else { + trans = gphttp.NewTransport() + if httpConfig.NoTLSVerify { + trans.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + } + if httpConfig.ResponseHeaderTimeout > 0 { + trans.ResponseHeaderTimeout = httpConfig.ResponseHeaderTimeout + } } service := base.TargetName() - rp := reverseproxy.NewReverseProxy(service, base.ProxyURL, trans) + rp := reverseproxy.NewReverseProxy(service, proxyURL, trans) if len(base.Middlewares) > 0 { err := middleware.PatchReverseProxy(rp, base.Middlewares) @@ -59,6 +70,20 @@ func NewReverseProxyRoute(base *Route) (*ReveseProxyRoute, gperr.Error) { } } + if a != nil { + headers := &agentproxy.AgentProxyHeaders{ + Host: base.ProxyURL.Host, + IsHTTPS: base.ProxyURL.Scheme == "https", + SkipTLSVerify: httpConfig.NoTLSVerify, + ResponseHeaderTimeout: int(httpConfig.ResponseHeaderTimeout.Seconds()), + } + ori := rp.HandlerFunc + rp.HandlerFunc = func(w http.ResponseWriter, r *http.Request) { + agentproxy.SetAgentProxyHeaders(r, headers) + ori(w, r) + } + } + r := &ReveseProxyRoute{ Route: base, rp: rp, @@ -72,6 +97,9 @@ func (r *ReveseProxyRoute) String() string { // Start implements task.TaskStarter. func (r *ReveseProxyRoute) Start(parent task.Parent) gperr.Error { + if existing, ok := routes.GetHTTPRoute(r.TargetName()); ok && !r.UseLoadBalance() { + return gperr.Errorf("route already exists: from provider %s and %s", existing.ProviderName(), r.ProviderName()) + } r.task = parent.Subtask("http."+r.TargetName(), false) switch { @@ -85,15 +113,15 @@ func (r *ReveseProxyRoute) Start(parent task.Parent) gperr.Error { r.HealthMon = waker case r.UseHealthCheck(): if r.IsDocker() { - client, err := docker.ConnectClient(r.Idlewatcher.DockerHost) + client, err := docker.NewClient(r.Container.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) + fallback := r.newHealthMonitor() + r.HealthMon = monitor.NewDockerHealthMonitor(client, r.Container.ContainerID, r.TargetName(), r.HealthCheck, fallback) r.task.OnCancel("close_docker_client", client.Close) } } if r.HealthMon == nil { - r.HealthMon = monitor.NewHTTPHealthMonitor(r.rp.TargetURL, r.HealthCheck) + r.HealthMon = r.newHealthMonitor() } } @@ -177,6 +205,17 @@ func (r *ReveseProxyRoute) HealthMonitor() health.HealthMonitor { return r.HealthMon } +func (r *ReveseProxyRoute) newHealthMonitor() interface { + health.HealthMonitor + health.HealthChecker +} { + if a := r.Agent(); a != nil { + target := monitor.AgentTargetFromURL(r.ProxyURL) + return monitor.NewAgentProxiedMonitor(a, r.HealthCheck, target) + } + return monitor.NewHTTPHealthMonitor(r.ProxyURL, r.HealthCheck) +} + func (r *ReveseProxyRoute) addToLoadBalancer(parent task.Parent) { var lb *loadbalancer.LoadBalancer cfg := r.LoadBalance @@ -186,7 +225,7 @@ func (r *ReveseProxyRoute) addToLoadBalancer(parent task.Parent) { linked = l.(*ReveseProxyRoute) lb = linked.loadBalancer lb.UpdateConfigIfNeeded(cfg) - if linked.Homepage.IsEmpty() && !r.Homepage.IsEmpty() { + if linked.Homepage == nil { linked.Homepage = r.Homepage } } else { @@ -205,7 +244,7 @@ func (r *ReveseProxyRoute) addToLoadBalancer(parent task.Parent) { } r.loadBalancer = lb - server := loadbalance.NewServer(r.task.Name(), r.rp.TargetURL, r.LoadBalance.Weight, r.handler, r.HealthMon) + server := loadbalance.NewServer(r.task.Name(), r.ProxyURL, r.LoadBalance.Weight, r.handler, r.HealthMon) lb.AddServer(server) r.task.OnCancel("lb_remove_server", func() { lb.RemoveServer(server) diff --git a/internal/route/route.go b/internal/route/route.go index 57466753..0f996805 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -2,21 +2,24 @@ package route import ( "fmt" - "strconv" "strings" + "github.com/docker/docker/api/types/container" + "github.com/yusing/go-proxy/agent/pkg/agent" + "github.com/yusing/go-proxy/internal" "github.com/yusing/go-proxy/internal/docker" idlewatcher "github.com/yusing/go-proxy/internal/docker/idlewatcher/types" "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/homepage" net "github.com/yusing/go-proxy/internal/net/types" "github.com/yusing/go-proxy/internal/task" + "github.com/yusing/go-proxy/internal/utils/strutils" "github.com/yusing/go-proxy/internal/watcher/health" "github.com/yusing/go-proxy/internal/common" - E "github.com/yusing/go-proxy/internal/error" - "github.com/yusing/go-proxy/internal/net/http/accesslog" - loadbalance "github.com/yusing/go-proxy/internal/net/http/loadbalancer/types" + config "github.com/yusing/go-proxy/internal/config/types" + "github.com/yusing/go-proxy/internal/net/gphttp/accesslog" + loadbalance "github.com/yusing/go-proxy/internal/net/gphttp/loadbalancer/types" "github.com/yusing/go-proxy/internal/route/rules" "github.com/yusing/go-proxy/internal/route/types" "github.com/yusing/go-proxy/internal/utils" @@ -38,7 +41,7 @@ type ( HealthCheck *health.HealthCheckConfig `json:"healthcheck,omitempty"` LoadBalance *loadbalance.Config `json:"load_balance,omitempty"` Middlewares map[string]docker.LabelMap `json:"middlewares,omitempty"` - Homepage *homepage.Item `json:"homepage,omitempty"` + Homepage *homepage.ItemConfig `json:"homepage,omitempty"` AccessLog *accesslog.Config `json:"access_log,omitempty"` Metadata `deserialize:"-"` @@ -160,6 +163,17 @@ func (r *Route) Type() types.RouteType { panic(fmt.Errorf("unexpected scheme %s for alias %s", r.Scheme, r.Alias)) } +func (r *Route) Agent() *agent.AgentConfig { + if r.Container == nil { + return nil + } + return r.Container.Agent +} + +func (r *Route) IsAgent() bool { + return r.Container != nil && r.Container.Agent != nil +} + func (r *Route) HealthMonitor() health.HealthMonitor { return r.impl.HealthMonitor() } @@ -176,8 +190,16 @@ func (r *Route) LoadBalanceConfig() *loadbalance.Config { return r.LoadBalance } -func (r *Route) HomepageConfig() *homepage.Item { - return r.Homepage +func (r *Route) HomepageConfig() *homepage.ItemConfig { + return r.Homepage.GetOverride(r.Alias) +} + +func (r *Route) HomepageItem() *homepage.Item { + return &homepage.Item{ + Alias: r.Alias, + Provider: r.Provider, + ItemConfig: r.HomepageConfig(), + } } func (r *Route) ContainerInfo() *docker.Container { @@ -202,7 +224,7 @@ func (r *Route) ShouldExclude() bool { return true case r.IsZeroPort() && !r.UseIdleWatcher(): return true - case r.Container.IsDatabase && !r.Container.IsExplicit: + case !r.Container.IsExplicit && r.Container.IsBlacklisted(): return true case strings.HasPrefix(r.Container.ContainerName, "buildx_"): return true @@ -244,76 +266,77 @@ func (r *Route) Finalize() { switch { case !isDocker: r.Host = "localhost" - case cont.PrivateIP != "": - r.Host = cont.PrivateIP - case cont.PublicIP != "": - r.Host = cont.PublicIP + case cont.PrivateHostname != "": + r.Host = cont.PrivateHostname + case cont.PublicHostname != "": + r.Host = cont.PublicHostname } } lp, pp := r.Port.Listening, r.Port.Proxy if isDocker { - if port, ok := common.ServiceNamePortMapTCP[cont.ImageName]; ok { + scheme, port, ok := getSchemePortByImageName(cont.Image.Name) + if ok { + if r.Scheme == "" { + r.Scheme = types.Scheme(scheme) + } if pp == 0 { pp = port } - if r.Scheme == "" { - r.Scheme = "tcp" - } - } else if port, ok := common.ImageNamePortMap[cont.ImageName]; ok { - if pp == 0 { - pp = port - } - if r.Scheme == "" { - r.Scheme = "http" - } + } + } + + if scheme, port, ok := getSchemePortByAlias(r.Alias); ok { + if r.Scheme == "" { + r.Scheme = types.Scheme(scheme) + } + if pp == 0 { + pp = port } } if pp == 0 { switch { - case r.Scheme == "https": - pp = 443 - case !isDocker: - pp = 80 - default: + case isDocker: pp = lowestPort(cont.PrivatePortMapping) if pp == 0 { pp = lowestPort(cont.PublicPortMapping) } + case r.Scheme == "https": + pp = 443 + default: + pp = 80 } } if isDocker { + if r.Scheme == "" { + for _, p := range cont.PublicPortMapping { + if p.PrivatePort == uint16(pp) && p.Type == "udp" { + r.Scheme = "udp" + break + } + } + } // replace private port with public port if using public IP. - if r.Host == cont.PublicIP { + if r.Host == cont.PublicHostname { if p, ok := cont.PrivatePortMapping[pp]; ok { pp = int(p.PublicPort) } - } - // replace public port with private port if using private IP. - if r.Host == cont.PrivateIP { + } else { + // replace public port with private port if using private IP. if p, ok := cont.PublicPortMapping[pp]; ok { pp = int(p.PrivatePort) } } - - if r.Scheme == "" { - switch { - case r.Host == cont.PublicIP && cont.PublicPortMapping[pp].Type == "udp": - r.Scheme = "udp" - case r.Host == cont.PrivateIP && cont.PrivatePortMapping[pp].Type == "udp": - r.Scheme = "udp" - } - } } if r.Scheme == "" { switch { case lp != 0: r.Scheme = "tcp" - case strings.HasSuffix(strconv.Itoa(pp), "443"): + case pp%1000 == 443: r.Scheme = "https" default: // assume its http r.Scheme = "http" @@ -323,7 +346,7 @@ func (r *Route) Finalize() { r.Port.Listening, r.Port.Proxy = lp, pp if r.HealthCheck == nil { - r.HealthCheck = health.DefaultHealthConfig + r.HealthCheck = health.DefaultHealthConfig() } if !r.HealthCheck.Disable { @@ -346,13 +369,68 @@ func (r *Route) Finalize() { cont.StopMethod = common.StopMethodDefault } } +} - if r.Homepage.IsEmpty() { - r.Homepage = homepage.NewItem(r.Alias) +func (r *Route) FinalizeHomepageConfig() { + if r.Alias == "" { + panic("alias is empty") + } + + isDocker := r.Container != nil + + if r.Homepage == nil { + r.Homepage = &homepage.ItemConfig{Show: true} + } + r.Homepage = r.Homepage.GetOverride(r.Alias) + + hp := r.Homepage + + var key string + if hp.Name == "" { + if r.Container != nil { + key = r.Container.Image.Name + } else { + key = r.Alias + } + displayName, ok := internal.GetDisplayName(key) + if ok { + hp.Name = displayName + } else { + hp.Name = strutils.Title( + strings.ReplaceAll( + strings.ReplaceAll(key, "-", " "), + "_", " ", + ), + ) + } + } + + if hp.Category == "" { + if config.GetInstance().Value().Homepage.UseDefaultCategories { + if isDocker { + key = r.Container.Image.Name + } else { + key = strings.ToLower(r.Alias) + } + if category, ok := homepage.PredefinedCategories[key]; ok { + hp.Category = category + } + } + + if hp.Category == "" { + switch { + case r.UseLoadBalance(): + hp.Category = "Load-balanced" + case isDocker: + hp.Category = "Docker" + default: + hp.Category = "Others" + } + } } } -func lowestPort(ports map[int]dockertypes.Port) (res int) { +func lowestPort(ports map[int]container.Port) (res int) { cmp := (uint16)(65535) for port, v := range ports { if v.PrivatePort < cmp { diff --git a/internal/route/routes/routequery/query.go b/internal/route/routes/routequery/query.go index 33a20700..f1b30374 100644 --- a/internal/route/routes/routequery/query.go +++ b/internal/route/routes/routequery/query.go @@ -1,15 +1,12 @@ package routequery import ( - "strings" "time" - "github.com/yusing/go-proxy/internal" "github.com/yusing/go-proxy/internal/homepage" - provider "github.com/yusing/go-proxy/internal/route/provider/types" "github.com/yusing/go-proxy/internal/route/routes" route "github.com/yusing/go-proxy/internal/route/types" - "github.com/yusing/go-proxy/internal/utils/strutils" + "github.com/yusing/go-proxy/internal/watcher/health" ) func getHealthInfo(r route.Route) map[string]string { @@ -28,13 +25,37 @@ func getHealthInfo(r route.Route) map[string]string { } } +type HealthInfoRaw struct { + Status health.Status + Latency time.Duration +} + +func getHealthInfoRaw(r route.Route) *HealthInfoRaw { + mon := r.HealthMonitor() + if mon == nil { + return &HealthInfoRaw{ + Status: health.StatusUnknown, + Latency: time.Duration(0), + } + } + return &HealthInfoRaw{ + Status: mon.Status(), + Latency: mon.Latency(), + } +} + func HealthMap() map[string]map[string]string { - healthMap := make(map[string]map[string]string) - routes.GetHTTPRoutes().RangeAll(func(alias string, r route.HTTPRoute) { + healthMap := make(map[string]map[string]string, routes.NumRoutes()) + routes.RangeRoutes(func(alias string, r route.Route) { healthMap[alias] = getHealthInfo(r) }) - routes.GetStreamRoutes().RangeAll(func(alias string, r route.StreamRoute) { - healthMap[alias] = getHealthInfo(r) + return healthMap +} + +func HealthInfo() map[string]*HealthInfoRaw { + healthMap := make(map[string]*HealthInfoRaw, routes.NumRoutes()) + routes.RangeRoutes(func(alias string, r route.Route) { + healthMap[alias] = getHealthInfoRaw(r) }) return healthMap } @@ -43,105 +64,33 @@ func HomepageCategories() []string { check := make(map[string]struct{}) categories := make([]string, 0) routes.GetHTTPRoutes().RangeAll(func(alias string, r route.HTTPRoute) { - homepage := r.HomepageConfig() - if homepage.IsEmpty() || homepage.Category == "" { + item := r.HomepageConfig() + if item == nil || item.Category == "" { return } - if _, ok := check[homepage.Category]; ok { + if _, ok := check[item.Category]; ok { return } - check[homepage.Category] = struct{}{} - categories = append(categories, homepage.Category) + check[item.Category] = struct{}{} + categories = append(categories, item.Category) }) return categories } -func HomepageConfig(useDefaultCategories bool, categoryFilter, providerFilter string) homepage.Categories { - hpCfg := homepage.NewHomePageConfig() +func HomepageConfig(categoryFilter, providerFilter string) homepage.Homepage { + hp := make(homepage.Homepage) routes.GetHTTPRoutes().RangeAll(func(alias string, r route.HTTPRoute) { - item := r.HomepageConfig() - - if item.IsEmpty() { - item = homepage.NewItem(alias) - } - - if override := item.GetOverride(); override != item { - if providerFilter != "" && override.Provider != providerFilter || - categoryFilter != "" && override.Category != categoryFilter { - return - } - hpCfg.Add(override) + if providerFilter != "" && r.ProviderName() != providerFilter { return } - - item.Alias = alias - item.Provider = r.ProviderName() - - if providerFilter != "" && item.Provider != providerFilter { - return - } - - if item.Name == "" { - reference := r.TargetName() - cont := r.ContainerInfo() - if cont != nil { - reference = cont.ImageName - } - name, ok := internal.GetDisplayName(reference) - if ok { - item.Name = name - } else { - item.Name = strutils.Title( - strings.ReplaceAll( - strings.ReplaceAll(alias, "-", " "), - "_", " ", - ), - ) - } - } - - if useDefaultCategories { - container := r.ContainerInfo() - if container != nil && item.Category == "" { - if category, ok := homepage.PredefinedCategories[container.ImageName]; ok { - item.Category = category - } - } - - if item.Category == "" { - if category, ok := homepage.PredefinedCategories[strings.ToLower(alias)]; ok { - item.Category = category - } - } - } - + item := r.HomepageItem() if categoryFilter != "" && item.Category != categoryFilter { return } - - switch { - case r.IsDocker(): - if item.Category == "" { - item.Category = "Docker" - } - item.SourceType = string(provider.ProviderTypeDocker) - case r.UseLoadBalance(): - if item.Category == "" { - item.Category = "Load-balanced" - } - item.SourceType = "loadbalancer" - default: - if item.Category == "" { - item.Category = "Others" - } - item.SourceType = string(provider.ProviderTypeFile) - } - - item.AltURL = r.TargetURL().String() - hpCfg.Add(item) + hp.Add(item) }) - return hpCfg + return hp } func RoutesByAlias(typeFilter ...route.RouteType) map[string]route.Route { diff --git a/internal/route/routes/routes.go b/internal/route/routes/routes.go index a372aa56..40e8e745 100644 --- a/internal/route/routes/routes.go +++ b/internal/route/routes/routes.go @@ -10,6 +10,19 @@ var ( streamRoutes = F.NewMapOf[string, types.StreamRoute]() ) +func RangeRoutes(callback func(alias string, r types.Route)) { + httpRoutes.RangeAll(func(alias string, r types.HTTPRoute) { + callback(alias, r) + }) + streamRoutes.RangeAll(func(alias string, r types.StreamRoute) { + callback(alias, r) + }) +} + +func NumRoutes() int { + return httpRoutes.Size() + streamRoutes.Size() +} + func GetHTTPRoutes() F.Map[string, types.HTTPRoute] { return httpRoutes } @@ -35,6 +48,14 @@ func GetStreamRoute(alias string) (types.StreamRoute, bool) { return streamRoutes.Load(alias) } +func GetRoute(alias string) (types.Route, bool) { + r, ok := httpRoutes.Load(alias) + if ok { + return r, true + } + return streamRoutes.Load(alias) +} + func SetHTTPRoute(alias string, r types.HTTPRoute) { httpRoutes.Store(alias, r) } diff --git a/internal/route/stream.go b/internal/route/stream.go index 2a6878b8..259e9baa 100755 --- a/internal/route/stream.go +++ b/internal/route/stream.go @@ -7,7 +7,7 @@ import ( "github.com/rs/zerolog" "github.com/yusing/go-proxy/internal/docker" "github.com/yusing/go-proxy/internal/docker/idlewatcher" - E "github.com/yusing/go-proxy/internal/error" + "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/logging" net "github.com/yusing/go-proxy/internal/net/types" "github.com/yusing/go-proxy/internal/route/routes" @@ -47,6 +47,9 @@ func (r *StreamRoute) String() string { // Start implements task.TaskStarter. func (r *StreamRoute) Start(parent task.Parent) gperr.Error { + if existing, ok := routes.GetStreamRoute(r.TargetName()); ok { + return gperr.Errorf("route already exists: from provider %s and %s", existing.ProviderName(), r.ProviderName()) + } r.task = parent.Subtask("stream." + r.TargetName()) r.Stream = NewStream(r) parent.OnCancel("finish", func() { @@ -64,10 +67,10 @@ func (r *StreamRoute) Start(parent task.Parent) gperr.Error { r.HealthMon = waker case r.UseHealthCheck(): if r.IsDocker() { - client, err := docker.ConnectClient(r.IdlewatcherConfig().DockerHost) + client, err := docker.NewClient(r.Container.DockerHost) if err == nil { fallback := monitor.NewRawHealthChecker(r.TargetURL(), r.HealthCheck) - r.HealthMon = monitor.NewDockerHealthMonitor(client, r.IdlewatcherConfig().ContainerID, r.TargetName(), r.HealthCheck, fallback) + r.HealthMon = monitor.NewDockerHealthMonitor(client, r.Container.ContainerID, r.TargetName(), r.HealthCheck, fallback) r.task.OnCancel("close_docker_client", client.Close) } } diff --git a/internal/route/types/route.go b/internal/route/types/route.go index 32fcda18..3011e03a 100644 --- a/internal/route/types/route.go +++ b/internal/route/types/route.go @@ -3,6 +3,7 @@ package types import ( "net/http" + "github.com/yusing/go-proxy/agent/pkg/agent" "github.com/yusing/go-proxy/internal/docker" idlewatcher "github.com/yusing/go-proxy/internal/docker/idlewatcher/types" "github.com/yusing/go-proxy/internal/homepage" @@ -10,7 +11,7 @@ import ( "github.com/yusing/go-proxy/internal/task" "github.com/yusing/go-proxy/internal/watcher/health" - loadbalance "github.com/yusing/go-proxy/internal/net/http/loadbalancer/types" + loadbalance "github.com/yusing/go-proxy/internal/net/gphttp/loadbalancer/types" ) type ( @@ -28,10 +29,14 @@ type ( IdlewatcherConfig() *idlewatcher.Config HealthCheckConfig() *health.HealthCheckConfig LoadBalanceConfig() *loadbalance.Config - HomepageConfig() *homepage.Item + HomepageConfig() *homepage.ItemConfig + HomepageItem() *homepage.Item ContainerInfo() *docker.Container + Agent() *agent.AgentConfig + IsDocker() bool + IsAgent() bool UseLoadBalance() bool UseIdleWatcher() bool UseHealthCheck() bool