diff --git a/internal/api/diagnostics_pprof.go b/internal/api/diagnostics_pprof.go deleted file mode 100644 index ddac620d3..000000000 --- a/internal/api/diagnostics_pprof.go +++ /dev/null @@ -1,56 +0,0 @@ -package api - -import ( - "net/http" - "net/http/pprof" - "os" - "strings" -) - -const pprofRoutePrefix = "/api/diagnostics/pprof" - -func pprofEnabled() bool { - return strings.EqualFold(os.Getenv("PULSE_ENABLE_PPROF"), "true") -} - -func (r *Router) handlePprofRedirect(w http.ResponseWriter, req *http.Request) { - if !pprofEnabled() { - http.NotFound(w, req) - return - } - - target := pprofRoutePrefix + "/" - if req.URL.RawQuery != "" { - target += "?" + req.URL.RawQuery - } - http.Redirect(w, req, target, http.StatusMovedPermanently) -} - -func (r *Router) handlePprof(w http.ResponseWriter, req *http.Request) { - if !pprofEnabled() { - http.NotFound(w, req) - return - } - - relative := strings.TrimPrefix(req.URL.Path, pprofRoutePrefix) - switch relative { - case "", "/": - pprof.Index(w, req) - return - case "/cmdline": - pprof.Cmdline(w, req) - return - case "/profile": - pprof.Profile(w, req) - return - case "/symbol": - pprof.Symbol(w, req) - return - case "/trace": - pprof.Trace(w, req) - return - default: - profile := strings.TrimPrefix(relative, "/") - pprof.Handler(profile).ServeHTTP(w, req) - } -} diff --git a/internal/api/diagnostics_pprof_test.go b/internal/api/diagnostics_pprof_test.go deleted file mode 100644 index 53e402ce6..000000000 --- a/internal/api/diagnostics_pprof_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package api - -import ( - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/rcourtman/pulse-go-rewrite/internal/config" -) - -func TestHandlePprofDisabledReturnsNotFound(t *testing.T) { - router := &Router{} - - req := httptest.NewRequest(http.MethodGet, "/api/diagnostics/pprof/", nil) - rec := httptest.NewRecorder() - - router.handlePprof(rec, req) - - if rec.Code != http.StatusNotFound { - t.Fatalf("status = %d, want %d", rec.Code, http.StatusNotFound) - } -} - -func TestHandlePprofEnabledServesIndex(t *testing.T) { - t.Setenv("PULSE_ENABLE_PPROF", "true") - router := &Router{} - - req := httptest.NewRequest(http.MethodGet, "/api/diagnostics/pprof/", nil) - rec := httptest.NewRecorder() - - router.handlePprof(rec, req) - - if rec.Code != http.StatusOK { - t.Fatalf("status = %d, want %d", rec.Code, http.StatusOK) - } - if !strings.Contains(rec.Body.String(), "heap") { - t.Fatalf("expected pprof index to include heap profile") - } -} - -func TestPprofRouteRequiresAdmin(t *testing.T) { - t.Setenv("PULSE_ENABLE_PPROF", "true") - t.Setenv("ALLOW_ADMIN_BYPASS", "") - t.Setenv("PULSE_DEV", "") - t.Setenv("NODE_ENV", "") - resetAdminBypassState() - - dataDir := t.TempDir() - cfg := &config.Config{ - DataPath: dataDir, - ConfigPath: dataDir, - AuthUser: "admin", - AuthPass: "secret", - } - - router := NewRouter(cfg, nil, nil, nil, nil, "1.0.0") - - req := httptest.NewRequest(http.MethodGet, "/api/diagnostics/pprof/", nil) - rec := httptest.NewRecorder() - - router.Handler().ServeHTTP(rec, req) - - if rec.Code != http.StatusUnauthorized { - t.Fatalf("status = %d, want %d", rec.Code, http.StatusUnauthorized) - } -} diff --git a/internal/api/proxy_admin_gating_test.go b/internal/api/proxy_admin_gating_test.go index c22f25f35..e6333e1d3 100644 --- a/internal/api/proxy_admin_gating_test.go +++ b/internal/api/proxy_admin_gating_test.go @@ -11,7 +11,6 @@ import ( func TestProxyAuthAdminGatesAdminEndpoints(t *testing.T) { t.Setenv("PULSE_DEV", "true") - t.Setenv("PULSE_ENABLE_PPROF", "true") record := newTokenRecord(t, "proxy-admin-gate-token-123.12345678", []string{config.ScopeSettingsRead}, nil) cfg := newTestConfigWithTokens(t, record) @@ -33,7 +32,6 @@ func TestProxyAuthAdminGatesAdminEndpoints(t *testing.T) { {method: http.MethodPost, path: "/api/logs/level", body: `{"level":"info"}`}, {method: http.MethodGet, path: "/api/diagnostics", body: ""}, {method: http.MethodPost, path: "/api/diagnostics/docker/prepare-token", body: `{}`}, - {method: http.MethodGet, path: "/api/diagnostics/pprof/", body: ""}, {method: http.MethodGet, path: "/api/system/settings", body: ""}, {method: http.MethodPost, path: "/api/system/settings/update", body: `{}`}, {method: http.MethodPost, path: "/api/security/oidc", body: `{}`}, diff --git a/internal/api/route_inventory_test.go b/internal/api/route_inventory_test.go index 6182ea198..b66cdc37b 100644 --- a/internal/api/route_inventory_test.go +++ b/internal/api/route_inventory_test.go @@ -310,8 +310,6 @@ var allRouteAllowlist = []string{ "/api/metrics-store/history", "/api/diagnostics", "/api/diagnostics/docker/prepare-token", - "/api/diagnostics/pprof", - "/api/diagnostics/pprof/", "/api/install/install-docker.sh", "/api/install/install.sh", "/api/install/install.ps1", diff --git a/internal/api/router.go b/internal/api/router.go index 9e27eaeae..5dfc8873f 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -325,10 +325,6 @@ func (r *Router) setupRoutes() { r.mux.HandleFunc("/api/metrics-store/history", RequireAuth(r.config, RequireScope(config.ScopeMonitoringRead, r.handleMetricsHistory))) r.mux.HandleFunc("/api/diagnostics", RequireAdmin(r.config, RequireScope(config.ScopeSettingsRead, r.handleDiagnostics))) r.mux.HandleFunc("/api/diagnostics/docker/prepare-token", RequireAdmin(r.config, RequireScope(config.ScopeSettingsWrite, r.handleDiagnosticsDockerPrepareToken))) - if pprofEnabled() { - r.mux.HandleFunc("/api/diagnostics/pprof", RequireAdmin(r.config, RequireScope(config.ScopeSettingsRead, r.handlePprofRedirect))) - r.mux.HandleFunc("/api/diagnostics/pprof/", RequireAdmin(r.config, RequireScope(config.ScopeSettingsRead, r.handlePprof))) - } r.mux.HandleFunc("/api/install/install-docker.sh", r.handleDownloadDockerInstallerScript) r.mux.HandleFunc("/api/install/install.sh", r.handleDownloadUnifiedInstallScript) r.mux.HandleFunc("/api/install/install.ps1", r.handleDownloadUnifiedInstallScriptPS)