mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-20 22:52:58 -05:00
pprof: Only handle if path matches /debug/pprof, add tests
This commit is contained in:
parent
a05a664d56
commit
4d9741dda6
4 changed files with 87 additions and 22 deletions
|
@ -20,7 +20,8 @@ func PProf(c *Controller) (middleware.Middleware, error) {
|
||||||
}
|
}
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return func(next middleware.Handler) middleware.Handler {
|
return func(next middleware.Handler) middleware.Handler {
|
||||||
return pprof.New(next)
|
return &pprof.Handler{Next: next, Mux: pprof.NewMux()}
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
2
dist/CHANGES.txt
vendored
2
dist/CHANGES.txt
vendored
|
@ -1,6 +1,8 @@
|
||||||
CHANGES
|
CHANGES
|
||||||
|
|
||||||
<master>
|
<master>
|
||||||
|
- New pprof directive for exposing process performance profile
|
||||||
|
- Toggle case-sensitive path matching with environment variable
|
||||||
- proxy: New max_conns setting to limit max connections per upstream
|
- proxy: New max_conns setting to limit max connections per upstream
|
||||||
- Internal improvements, restructuring, and bug fixes
|
- Internal improvements, restructuring, and bug fixes
|
||||||
|
|
||||||
|
|
|
@ -7,28 +7,35 @@ import (
|
||||||
"github.com/mholt/caddy/middleware"
|
"github.com/mholt/caddy/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
//Handler is a simple struct whose ServeHTTP will delegate relevant pprof endpoints to net/http/pprof
|
// BasePath is the base path to match for all pprof requests.
|
||||||
type handler struct {
|
const BasePath = "/debug/pprof"
|
||||||
mux *http.ServeMux
|
|
||||||
|
// Handler is a simple struct whose ServeHTTP will delegate pprof
|
||||||
|
// endpoints to their equivalent net/http/pprof handlers.
|
||||||
|
type Handler struct {
|
||||||
|
Next middleware.Handler
|
||||||
|
Mux *http.ServeMux
|
||||||
}
|
}
|
||||||
|
|
||||||
//New creates a new pprof middleware
|
// ServeHTTP handles requests to BasePath with pprof, or passes
|
||||||
func New(next middleware.Handler) middleware.Handler {
|
// all other requests up the chain.
|
||||||
//pretty much copying what pprof does on init: https://golang.org/src/net/http/pprof/pprof.go#L67
|
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
|
if middleware.Path(r.URL.Path).Matches(BasePath) {
|
||||||
|
h.Mux.ServeHTTP(w, r)
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return h.Next.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMux returns a new http.ServeMux that routes pprof requests.
|
||||||
|
// It pretty much copies what the std lib pprof does on init:
|
||||||
|
// https://golang.org/src/net/http/pprof/pprof.go#L67
|
||||||
|
func NewMux() *http.ServeMux {
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc("/debug/pprof/", pp.Index)
|
mux.HandleFunc(BasePath+"/", pp.Index)
|
||||||
mux.HandleFunc("/debug/pprof/cmdline", pp.Cmdline)
|
mux.HandleFunc(BasePath+"/cmdline", pp.Cmdline)
|
||||||
mux.HandleFunc("/debug/pprof/profile", pp.Profile)
|
mux.HandleFunc(BasePath+"/profile", pp.Profile)
|
||||||
mux.HandleFunc("/debug/pprof/symbol", pp.Symbol)
|
mux.HandleFunc(BasePath+"/symbol", pp.Symbol)
|
||||||
mux.HandleFunc("/debug/pprof/trace", pp.Trace)
|
mux.HandleFunc(BasePath+"/trace", pp.Trace)
|
||||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
return mux
|
||||||
next.ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
return &handler{mux}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
|
||||||
rec := middleware.NewResponseRecorder(w)
|
|
||||||
h.mux.ServeHTTP(rec, r)
|
|
||||||
return rec.Status(), nil
|
|
||||||
}
|
}
|
||||||
|
|
55
middleware/pprof/pprof_test.go
Normal file
55
middleware/pprof/pprof_test.go
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package pprof
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mholt/caddy/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestServeHTTP(t *testing.T) {
|
||||||
|
h := Handler{
|
||||||
|
Next: middleware.HandlerFunc(nextHandler),
|
||||||
|
Mux: NewMux(),
|
||||||
|
}
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
r, err := http.NewRequest("GET", "/debug/pprof", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
status, err := h.ServeHTTP(w, r)
|
||||||
|
|
||||||
|
if status != 0 {
|
||||||
|
t.Errorf("Expected status %d but got %d", 0, status)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected nil error, but got: %v", err)
|
||||||
|
}
|
||||||
|
if w.Body.String() == "content" {
|
||||||
|
t.Errorf("Expected pprof to handle request, but it didn't")
|
||||||
|
}
|
||||||
|
|
||||||
|
w = httptest.NewRecorder()
|
||||||
|
r, err = http.NewRequest("GET", "/foo", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
status, err = h.ServeHTTP(w, r)
|
||||||
|
if status != http.StatusNotFound {
|
||||||
|
t.Errorf("Test two: Expected status %d but got %d", http.StatusNotFound, status)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Test two: Expected nil error, but got: %v", err)
|
||||||
|
}
|
||||||
|
if w.Body.String() != "content" {
|
||||||
|
t.Errorf("Expected pprof to pass the request thru, but it didn't; got: %s", w.Body.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func nextHandler(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
|
fmt.Fprintf(w, "content")
|
||||||
|
return http.StatusNotFound, nil
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue