diff --git a/cmd/main.go b/cmd/main.go index b50396f..154bc90 100755 --- a/cmd/main.go +++ b/cmd/main.go @@ -4,6 +4,7 @@ import ( "encoding/json" "log" "os" + "sync" "github.com/yusing/go-proxy/internal" "github.com/yusing/go-proxy/internal/api/v1/auth" @@ -22,6 +23,18 @@ import ( var rawLogger = log.New(os.Stdout, "", 0) +func parallel(fns ...func()) { + var wg sync.WaitGroup + for _, fn := range fns { + wg.Add(1) + go func() { + defer wg.Done() + fn() + }() + } + wg.Wait() +} + func main() { initProfiling() args := pkg.GetArgs(common.MainServerCommandValidator{}) @@ -64,6 +77,11 @@ func main() { if args.Command == common.CommandStart { logging.Info().Msgf("GoDoxy version %s", pkg.GetVersion()) logging.Trace().Msg("trace enabled") + parallel( + internal.InitIconListCache, + homepage.InitOverridesConfig, + favicon.InitIconCache, + ) // logging.AddHook(notif.GetDispatcher()) } else { logging.DiscardLogger() @@ -109,10 +127,6 @@ func main() { return } - go internal.InitIconListCache() - go homepage.InitOverridesConfig() - go favicon.InitIconCache() - cfg.Start(&config.StartServersOptions{ Proxy: true, }) diff --git a/internal/api/v1/favicon/cache.go b/internal/api/v1/favicon/cache.go index 908a072..cfc1ba4 100644 --- a/internal/api/v1/favicon/cache.go +++ b/internal/api/v1/favicon/cache.go @@ -36,7 +36,7 @@ func InitIconCache() { if err != nil { logging.Error().Err(err).Msg("failed to load icon cache") } else { - logging.Info().Msgf("icon cache loaded (%d icons)", len(iconCache)) + logging.Info().Int("count", len(iconCache)).Msg("icon cache loaded") } go func() { diff --git a/internal/api/v1/list.go b/internal/api/v1/list.go index cdb520b..6e59ea7 100644 --- a/internal/api/v1/list.go +++ b/internal/api/v1/list.go @@ -56,7 +56,7 @@ func List(cfg config.ConfigInstance, w http.ResponseWriter, r *http.Request) { case ListMatchDomains: gphttp.RespondJSON(w, r, cfg.Value().MatchDomains) case ListHomepageConfig: - gphttp.RespondJSON(w, r, routequery.HomepageConfig(cfg.Value().Homepage.UseDefaultCategories, r.FormValue("category"), r.FormValue("provider"))) + gphttp.RespondJSON(w, r, routequery.HomepageConfig(r.FormValue("category"), r.FormValue("provider"))) case ListRouteProviders: gphttp.RespondJSON(w, r, cfg.RouteProviderList()) case ListHomepageCategories: diff --git a/internal/homepage/homepage.go b/internal/homepage/homepage.go index 6da2aed..beda6ef 100644 --- a/internal/homepage/homepage.go +++ b/internal/homepage/homepage.go @@ -23,10 +23,8 @@ type ( Item struct { *ItemConfig - Alias string `json:"alias"` // proxy alias - SourceType string `json:"source_type"` - AltURL string `json:"alt_url"` // original proxy target - Provider string `json:"provider"` + Alias string `json:"alias"` // proxy alias + Provider string `json:"provider"` IsUnset bool `json:"-"` } diff --git a/internal/homepage/override_config.go b/internal/homepage/override_config.go index c8ac779..6d8400c 100644 --- a/internal/homepage/override_config.go +++ b/internal/homepage/override_config.go @@ -32,7 +32,9 @@ func InitOverridesConfig() { if err != nil { logging.Error().Err(err).Msg("failed to load homepage overrides config") } else { - logging.Info().Msgf("homepage overrides config loaded, %d items", len(overrideConfigInstance.ItemOverrides)) + logging.Info(). + Int("count", len(overrideConfigInstance.ItemOverrides)). + Msg("homepage overrides config loaded") } task.OnProgramExit("save_homepage_json_config", func() { if len(overrideConfigInstance.ItemOverrides) == 0 { diff --git a/internal/list-icons.go b/internal/list-icons.go index 18f341c..c708da9 100644 --- a/internal/list-icons.go +++ b/internal/list-icons.go @@ -12,7 +12,6 @@ import ( "github.com/yusing/go-proxy/internal/common" "github.com/yusing/go-proxy/internal/logging" "github.com/yusing/go-proxy/internal/utils" - "github.com/yusing/go-proxy/internal/utils/strutils" ) type GitHubContents struct { //! keep this, may reuse in future @@ -66,10 +65,10 @@ func InitIconListCache() { logging.Error().Err(err).Msg("failed to load icon list cache config") } else if stats, err := os.Stat(common.IconListCachePath); err == nil { lastUpdate = stats.ModTime() - logging.Info().Msgf("icon list cache loaded (%d icons, %d display names), last updated at %s", - len(iconsCache.IconList), - len(iconsCache.DisplayNames), - strutils.FormatTime(lastUpdate)) + logging.Info(). + Int("icons", len(iconsCache.IconList)). + Int("display_names", len(iconsCache.DisplayNames)). + Msg("icon list cache loaded") } } @@ -86,12 +85,15 @@ func ListAvailableIcons() (*Cache, error) { iconsCahceMu.Lock() defer iconsCahceMu.Unlock() + logging.Info().Msg("updating icon data") icons, err := fetchIconData() if err != nil { return nil, err } - - logging.Info().Msg("icons list updated") + logging.Info(). + Int("icons", len(icons.IconList)). + Int("display_names", len(icons.DisplayNames)). + Msg("icons list updated") iconsCache = icons lastUpdate = time.Now() diff --git a/internal/route/provider/provider.go b/internal/route/provider/provider.go index 6894879..f75e8ba 100644 --- a/internal/route/provider/provider.go +++ b/internal/route/provider/provider.go @@ -87,6 +87,7 @@ func (p *Provider) MarshalText() ([]byte, error) { } func (p *Provider) startRoute(parent task.Parent, r *route.Route) gperr.Error { + r.FinalizeHomepageConfig() err := r.Start(parent) if err != nil { delete(p.routes, r.Alias) diff --git a/internal/route/route.go b/internal/route/route.go index 2ae9edb..56bf003 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -17,6 +17,7 @@ import ( dockertypes "github.com/docker/docker/api/types" "github.com/yusing/go-proxy/internal/common" + 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" @@ -356,13 +357,27 @@ 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") } - if r.Homepage.Name == "" { - var key string + isDocker := r.Container != nil + + hp := r.Homepage + if hp.IsEmpty() { + hp = homepage.NewItem(r.Alias) + } + hp = hp.GetOverride() + hp.Alias = r.Alias + hp.Provider = r.Provider + + r.Homepage = hp + + var key string + if hp.Name == "" { if r.Container != nil { key = r.Container.ImageName } else { @@ -370,16 +385,40 @@ func (r *Route) Finalize() { } displayName, ok := internal.GetDisplayName(key) if ok { - r.Homepage.Name = displayName + hp.Name = displayName } else { - r.Homepage.Name = strutils.Title( + hp.Name = strutils.Title( strings.ReplaceAll( - strings.ReplaceAll(r.Alias, "-", " "), + strings.ReplaceAll(key, "-", " "), "_", " ", ), ) } } + + if hp.Category == "" { + if config.GetInstance().Value().Homepage.UseDefaultCategories { + if isDocker { + key = r.Container.ImageName + } 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) { diff --git a/internal/route/routes/routequery/query.go b/internal/route/routes/routequery/query.go index a7bda4e..227d722 100644 --- a/internal/route/routes/routequery/query.go +++ b/internal/route/routes/routequery/query.go @@ -1,11 +1,9 @@ package routequery import ( - "strings" "time" "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/watcher/health" @@ -79,70 +77,17 @@ func HomepageCategories() []string { return categories } -func HomepageConfig(useDefaultCategories bool, categoryFilter, providerFilter string) homepage.Categories { +func HomepageConfig(categoryFilter, providerFilter string) homepage.Categories { hpCfg := homepage.NewHomePageConfig() routes.GetHTTPRoutes().RangeAll(func(alias string, r route.HTTPRoute) { item := r.HomepageConfig() - - if override := item.GetOverride(); override != item { - if providerFilter != "" && override.Provider != providerFilter || - categoryFilter != "" && override.Category != categoryFilter { - return - } - hpCfg.Add(override) - return - } - - item.Alias = alias - item.Provider = r.ProviderName() - if providerFilter != "" && item.Provider != providerFilter { return } - - 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 - } - } - } - if categoryFilter != "" && item.Category != categoryFilter { return } - - switch { - case r.IsDocker(): - if item.Category == "" { - item.Category = "Docker" - } - if r.IsAgent() { - item.SourceType = string(provider.ProviderTypeAgent) - } else { - 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) }) return hpCfg