diff --git a/cmd/main.go b/cmd/main.go index b38fc0e..2ad2247 100755 --- a/cmd/main.go +++ b/cmd/main.go @@ -18,7 +18,7 @@ import ( E "github.com/yusing/go-proxy/internal/error" "github.com/yusing/go-proxy/internal/logging" "github.com/yusing/go-proxy/internal/net/http/middleware" - "github.com/yusing/go-proxy/internal/route/routes" + "github.com/yusing/go-proxy/internal/route/routes/routequery" "github.com/yusing/go-proxy/internal/task" "github.com/yusing/go-proxy/pkg" ) @@ -104,7 +104,7 @@ func main() { switch args.Command { case common.CommandListRoutes: cfg.StartProxyProviders() - printJSON(routes.RoutesByAlias()) + printJSON(routequery.RoutesByAlias()) return case common.CommandListConfigs: printJSON(cfg.Value()) @@ -113,7 +113,7 @@ func main() { printJSON(cfg.DumpEntries()) return case common.CommandDebugListProviders: - printJSON(cfg.DumpProviders()) + printJSON(cfg.DumpRouteProviders()) return } diff --git a/internal/api/v1/health.go b/internal/api/v1/health.go index 82fe9a5..0a3c011 100644 --- a/internal/api/v1/health.go +++ b/internal/api/v1/health.go @@ -8,11 +8,11 @@ import ( "github.com/coder/websocket/wsjson" U "github.com/yusing/go-proxy/internal/api/v1/utils" config "github.com/yusing/go-proxy/internal/config/types" - "github.com/yusing/go-proxy/internal/route/routes" + "github.com/yusing/go-proxy/internal/route/routes/routequery" ) func HealthWS(cfg config.ConfigInstance, w http.ResponseWriter, r *http.Request) { U.PeriodicWS(cfg, w, r, 1*time.Second, func(conn *websocket.Conn) error { - return wsjson.Write(r.Context(), conn, routes.HealthMap()) + return wsjson.Write(r.Context(), conn, routequery.HealthMap()) }) } diff --git a/internal/api/v1/list.go b/internal/api/v1/list.go index 08fb8bd..94121be 100644 --- a/internal/api/v1/list.go +++ b/internal/api/v1/list.go @@ -8,21 +8,23 @@ import ( "github.com/yusing/go-proxy/internal/common" config "github.com/yusing/go-proxy/internal/config/types" "github.com/yusing/go-proxy/internal/net/http/middleware" - "github.com/yusing/go-proxy/internal/route/routes" + "github.com/yusing/go-proxy/internal/route/routes/routequery" route "github.com/yusing/go-proxy/internal/route/types" "github.com/yusing/go-proxy/internal/task" "github.com/yusing/go-proxy/internal/utils" ) const ( - ListRoute = "route" - ListRoutes = "routes" - ListFiles = "files" - ListMiddlewares = "middlewares" - ListMiddlewareTraces = "middleware_trace" - ListMatchDomains = "match_domains" - ListHomepageConfig = "homepage_config" - ListTasks = "tasks" + ListRoute = "route" + ListRoutes = "routes" + ListFiles = "files" + ListMiddlewares = "middlewares" + ListMiddlewareTraces = "middleware_trace" + ListMatchDomains = "match_domains" + ListHomepageConfig = "homepage_config" + ListRouteProviders = "route_providers" + ListHomepageCategories = "homepage_categories" + ListTasks = "tasks" ) func List(cfg config.ConfigInstance, w http.ResponseWriter, r *http.Request) { @@ -41,7 +43,7 @@ func List(cfg config.ConfigInstance, w http.ResponseWriter, r *http.Request) { U.RespondJSON(w, r, route) } case ListRoutes: - U.RespondJSON(w, r, routes.RoutesByAlias(route.RouteType(r.FormValue("type")))) + U.RespondJSON(w, r, routequery.RoutesByAlias(route.RouteType(r.FormValue("type")))) case ListFiles: listFiles(w, r) case ListMiddlewares: @@ -51,7 +53,11 @@ func List(cfg config.ConfigInstance, w http.ResponseWriter, r *http.Request) { case ListMatchDomains: U.RespondJSON(w, r, cfg.Value().MatchDomains) case ListHomepageConfig: - U.RespondJSON(w, r, routes.HomepageConfig(cfg.Value().Homepage.UseDefaultCategories)) + U.RespondJSON(w, r, routequery.HomepageConfig(cfg.Value().Homepage.UseDefaultCategories, r.FormValue("category"), r.FormValue("provider"))) + case ListRouteProviders: + U.RespondJSON(w, r, cfg.RouteProviderList()) + case ListHomepageCategories: + U.RespondJSON(w, r, routequery.HomepageCategories()) case ListTasks: U.RespondJSON(w, r, task.DebugTaskList()) default: @@ -63,9 +69,9 @@ func List(cfg config.ConfigInstance, w http.ResponseWriter, r *http.Request) { // otherwise, return a single Route with alias which or nil if not found. func listRoute(which string) any { if which == "" || which == "all" { - return routes.RoutesByAlias() + return routequery.RoutesByAlias() } - routes := routes.RoutesByAlias() + routes := routequery.RoutesByAlias() route, ok := routes[which] if !ok { return nil diff --git a/internal/config/query.go b/internal/config/query.go index 9d68ca0..c1899f6 100644 --- a/internal/config/query.go +++ b/internal/config/query.go @@ -16,7 +16,7 @@ func (cfg *Config) DumpEntries() map[string]*types.RawEntry { return entries } -func (cfg *Config) DumpProviders() map[string]*provider.Provider { +func (cfg *Config) DumpRouteProviders() map[string]*provider.Provider { entries := make(map[string]*provider.Provider) cfg.providers.RangeAll(func(_ string, p *provider.Provider) { entries[p.ShortName()] = p @@ -24,6 +24,14 @@ func (cfg *Config) DumpProviders() map[string]*provider.Provider { return entries } +func (cfg *Config) RouteProviderList() []string { + var list []string + cfg.providers.RangeAll(func(_ string, p *provider.Provider) { + list = append(list, p.ShortName()) + }) + return list +} + func (cfg *Config) Statistics() map[string]any { var rps, streams provider.RouteStats var total uint16 diff --git a/internal/config/types/config.go b/internal/config/types/config.go index ca4a0ac..8640c78 100644 --- a/internal/config/types/config.go +++ b/internal/config/types/config.go @@ -33,6 +33,7 @@ type ( Value() *Config Reload() E.Error Statistics() map[string]any + RouteProviderList() []string Context() context.Context } ) diff --git a/internal/homepage/categories.go b/internal/homepage/categories.go index 80e4d67..b2a99ca 100644 --- a/internal/homepage/categories.go +++ b/internal/homepage/categories.go @@ -33,7 +33,6 @@ var PredefinedCategories = map[string]string{ "changedetection": "Monitoring", "influxdb": "Monitoring", "influx": "Monitoring", - "dozzle": "Monitoring", "adguardhome": "Networking", "adgh": "Networking", @@ -47,6 +46,8 @@ var PredefinedCategories = map[string]string{ "dockge": "Container Management", "portainer-ce": "Container Management", "portainer-be": "Container Management", + "logs": "Container Management", + "dozzle": "Container Management", "rss": "RSS", "rsshub": "RSS", @@ -57,6 +58,7 @@ var PredefinedCategories = map[string]string{ "paperless": "Documents", "paperless-ngx": "Documents", "s-pdf": "Documents", + "stirling-pdf": "Documents", "minio": "Storage", "filebrowser": "Storage", diff --git a/internal/homepage/homepage.go b/internal/homepage/homepage.go index 5e54fc3..dc402dd 100644 --- a/internal/homepage/homepage.go +++ b/internal/homepage/homepage.go @@ -17,6 +17,7 @@ type ( Alias string `json:"alias"` // proxy alias SourceType string `json:"source_type"` AltURL string `json:"alt_url"` // original proxy target + Provider string `json:"provider"` } ) diff --git a/internal/route/provider/docker.go b/internal/route/provider/docker.go index 1269c00..3022ebd 100755 --- a/internal/route/provider/docker.go +++ b/internal/route/provider/docker.go @@ -90,7 +90,7 @@ func (p *DockerProvider) loadRoutesImpl() (route.Routes, E.Error) { }) } - routes, err = route.FromEntries(entries) + routes, err = route.FromEntries(p.ShortName(), entries) errs.Add(err) return routes, errs.Error() diff --git a/internal/route/provider/file.go b/internal/route/provider/file.go index 3098d53..c9c51e5 100644 --- a/internal/route/provider/file.go +++ b/internal/route/provider/file.go @@ -32,16 +32,16 @@ func FileProviderImpl(filename string) (ProviderImpl, error) { return impl, nil } -func validate(data []byte) (route.Routes, E.Error) { +func validate(provider string, data []byte) (route.Routes, E.Error) { entries, err := utils.DeserializeYAMLMap[*route.RawEntry](data) if err != nil { return route.NewRoutes(), err } - return route.FromEntries(entries) + return route.FromEntries(provider, entries) } func Validate(data []byte) (err E.Error) { - _, err = validate(data) + _, err = validate("", data) return } @@ -69,7 +69,7 @@ func (p *FileProvider) loadRoutesImpl() (route.Routes, E.Error) { return routes, E.From(err) } - return validate(data) + return validate(p.ShortName(), data) } func (p *FileProvider) NewWatcher() W.Watcher { diff --git a/internal/route/provider/file_test.go b/internal/route/provider/file_test.go index 756095c..cf15c8d 100644 --- a/internal/route/provider/file_test.go +++ b/internal/route/provider/file_test.go @@ -12,6 +12,6 @@ import ( var testAllFieldsYAML []byte func TestFile(t *testing.T) { - _, err := validate(testAllFieldsYAML) + _, err := validate("", testAllFieldsYAML) ExpectNoError(t, err) } diff --git a/internal/route/route.go b/internal/route/route.go index 220f5db..0e04530 100755 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -76,7 +76,7 @@ func NewRoute(raw *RawEntry) (*Route, E.Error) { }, nil } -func FromEntries(entries RawEntries) (Routes, E.Error) { +func FromEntries(provider string, entries RawEntries) (Routes, E.Error) { b := E.NewBuilder("errors in routes") routes := NewRoutes() @@ -85,6 +85,7 @@ func FromEntries(entries RawEntries) (Routes, E.Error) { en = new(RawEntry) } en.Alias = alias + en.Provider = provider if strings.HasPrefix(alias, "x-") { // x properties return } diff --git a/internal/route/routes/query.go b/internal/route/routes/routequery/query.go similarity index 68% rename from internal/route/routes/query.go rename to internal/route/routes/routequery/query.go index c06a22d..46ee142 100644 --- a/internal/route/routes/query.go +++ b/internal/route/routes/routequery/query.go @@ -1,4 +1,4 @@ -package routes +package routequery import ( "strings" @@ -7,6 +7,7 @@ import ( "github.com/yusing/go-proxy/internal/homepage" "github.com/yusing/go-proxy/internal/route/entry" 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" ) @@ -29,18 +30,36 @@ func getHealthInfo(r route.Route) map[string]string { func HealthMap() map[string]map[string]string { healthMap := make(map[string]map[string]string) - httpRoutes.RangeAll(func(alias string, r route.HTTPRoute) { + routes.GetHTTPRoutes().RangeAll(func(alias string, r route.HTTPRoute) { healthMap[alias] = getHealthInfo(r) }) - streamRoutes.RangeAll(func(alias string, r route.StreamRoute) { + routes.GetStreamRoutes().RangeAll(func(alias string, r route.StreamRoute) { healthMap[alias] = getHealthInfo(r) }) return healthMap } -func HomepageConfig(useDefaultCategories bool) homepage.Config { +func HomepageCategories() []string { + check := make(map[string]struct{}) + categories := make([]string, 0) + routes.GetHTTPRoutes().RangeAll(func(alias string, r route.HTTPRoute) { + en := r.RawEntry() + if en.Homepage == nil || en.Homepage.Category == "" { + return + } + if _, ok := check[en.Homepage.Category]; ok { + return + } + check[en.Homepage.Category] = struct{}{} + categories = append(categories, en.Homepage.Category) + }) + return categories +} + +func HomepageConfig(useDefaultCategories bool, categoryFilter, providerFilter string) homepage.Config { hpCfg := homepage.NewHomePageConfig() - GetHTTPRoutes().RangeAll(func(alias string, r route.HTTPRoute) { + + routes.GetHTTPRoutes().RangeAll(func(alias string, r route.HTTPRoute) { en := r.RawEntry() item := en.Homepage if item == nil { @@ -57,6 +76,11 @@ func HomepageConfig(useDefaultCategories bool) homepage.Config { } item.Alias = alias + item.Provider = r.RawEntry().Provider + + if providerFilter != "" && item.Provider != providerFilter { + return + } if item.Name == "" { item.Name = strutils.Title( @@ -81,6 +105,10 @@ func HomepageConfig(useDefaultCategories bool) homepage.Config { } } + if categoryFilter != "" && item.Category != categoryFilter { + return + } + switch { case entry.IsDocker(r): if item.Category == "" { @@ -113,11 +141,11 @@ func RoutesByAlias(typeFilter ...route.RouteType) map[string]route.Route { for _, t := range typeFilter { switch t { case route.RouteTypeReverseProxy: - GetHTTPRoutes().RangeAll(func(alias string, r route.HTTPRoute) { + routes.GetHTTPRoutes().RangeAll(func(alias string, r route.HTTPRoute) { rts[alias] = r }) case route.RouteTypeStream: - GetStreamRoutes().RangeAll(func(alias string, r route.StreamRoute) { + routes.GetStreamRoutes().RangeAll(func(alias string, r route.StreamRoute) { rts[alias] = r }) } diff --git a/internal/route/types/raw_entry.go b/internal/route/types/raw_entry.go index b3a1479..d4dddb1 100644 --- a/internal/route/types/raw_entry.go +++ b/internal/route/types/raw_entry.go @@ -40,6 +40,7 @@ type ( /* Docker only */ Container *docker.Container `json:"container,omitempty"` + Provider string `json:"provider,omitempty"` finalized bool }