feat(developer): add pprof endpoint

This commit is contained in:
Siyuan Miao 2025-04-15 01:05:30 +02:00
parent b24191d14e
commit 58605718d0
1 changed files with 63 additions and 3 deletions

66
web.go
View File

@ -9,6 +9,7 @@ import (
"fmt"
"io/fs"
"net/http"
"net/http/pprof"
"path/filepath"
"strings"
"time"
@ -103,6 +104,25 @@ func setupRouter() *gin.Engine {
// A Prometheus metrics endpoint.
r.GET("/metrics", gin.WrapH(promhttp.Handler()))
// Developer mode protected routes
developerModeRouter := r.Group("/developer/")
developerModeRouter.Use(basicAuthProtectedMiddleware(true))
{
// pprof
developerModeRouter.GET("/pprof/", gin.WrapF(pprof.Index))
developerModeRouter.GET("/pprof/cmdline", gin.WrapF(pprof.Cmdline))
developerModeRouter.GET("/pprof/profile", gin.WrapF(pprof.Profile))
developerModeRouter.POST("/pprof/symbol", gin.WrapF(pprof.Symbol))
developerModeRouter.GET("/pprof/symbol", gin.WrapF(pprof.Symbol))
developerModeRouter.GET("/pprof/trace", gin.WrapF(pprof.Trace))
developerModeRouter.GET("/pprof/allocs", gin.WrapH(pprof.Handler("allocs")))
developerModeRouter.GET("/pprof/block", gin.WrapH(pprof.Handler("block")))
developerModeRouter.GET("/pprof/goroutine", gin.WrapH(pprof.Handler("goroutine")))
developerModeRouter.GET("/pprof/heap", gin.WrapH(pprof.Handler("heap")))
developerModeRouter.GET("/pprof/mutex", gin.WrapH(pprof.Handler("mutex")))
developerModeRouter.GET("/pprof/threadcreate", gin.WrapH(pprof.Handler("threadcreate")))
}
// Protected routes (allows both password and noPassword modes)
protected := r.Group("/")
protected.Use(protectedMiddleware())
@ -464,11 +484,51 @@ func protectedMiddleware() gin.HandlerFunc {
}
}
func sendErrorJsonThenAbort(c *gin.Context, status int, message string) {
c.JSON(status, gin.H{"error": message})
c.Abort()
}
func basicAuthProtectedMiddleware(requireDeveloperMode bool) gin.HandlerFunc {
return func(c *gin.Context) {
if requireDeveloperMode {
devModeState, err := rpcGetDevModeState()
if err != nil {
sendErrorJsonThenAbort(c, http.StatusInternalServerError, "Failed to get developer mode state")
return
}
if !devModeState.Enabled {
sendErrorJsonThenAbort(c, http.StatusUnauthorized, "Developer mode is not enabled")
return
}
}
if config.LocalAuthMode == "noPassword" {
sendErrorJsonThenAbort(c, http.StatusForbidden, "The resource is not available in noPassword mode")
return
}
// calculate basic auth credentials
_, password, ok := c.Request.BasicAuth()
if !ok {
c.Header("WWW-Authenticate", "Basic realm=\"JetKVM\"")
sendErrorJsonThenAbort(c, http.StatusUnauthorized, "Basic auth is required")
return
}
err := bcrypt.CompareHashAndPassword([]byte(config.HashedPassword), []byte(password))
if err != nil {
sendErrorJsonThenAbort(c, http.StatusUnauthorized, "Invalid password")
return
}
c.Next()
}
}
func RunWebServer() {
r := setupRouter()
//if strings.Contains(builtAppVersion, "-dev") {
// pprof.Register(r)
//}
err := r.Run(":80")
if err != nil {
panic(err)