1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
// Package expvarhandler provides fasthttp-compatible request handler
// serving expvars.
package expvarhandler
import (
"expvar"
"fmt"
"regexp"
"github.com/valyala/fasthttp"
)
var (
expvarHandlerCalls = expvar.NewInt("expvarHandlerCalls")
expvarRegexpErrors = expvar.NewInt("expvarRegexpErrors")
defaultRE = regexp.MustCompile(".")
)
// ExpvarHandler dumps json representation of expvars to http response.
//
// Expvars may be filtered by regexp provided via 'r' query argument.
//
// See https://pkg.go.dev/expvar for details.
func ExpvarHandler(ctx *fasthttp.RequestCtx) {
expvarHandlerCalls.Add(1)
ctx.Response.Reset()
r, err := getExpvarRegexp(ctx)
if err != nil {
expvarRegexpErrors.Add(1)
fmt.Fprintf(ctx, "Error when obtaining expvar regexp: %v", err)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return
}
fmt.Fprintf(ctx, "{\n")
first := true
expvar.Do(func(kv expvar.KeyValue) {
if r.MatchString(kv.Key) {
if !first {
fmt.Fprintf(ctx, ",\n")
}
first = false
fmt.Fprintf(ctx, "\t%q: %s", kv.Key, kv.Value)
}
})
fmt.Fprintf(ctx, "\n}\n")
ctx.SetContentType("application/json; charset=utf-8")
}
func getExpvarRegexp(ctx *fasthttp.RequestCtx) (*regexp.Regexp, error) {
r := string(ctx.QueryArgs().Peek("r"))
if r == "" {
return defaultRE, nil
}
rr, err := regexp.Compile(r)
if err != nil {
return nil, fmt.Errorf("cannot parse r=%q: %w", r, err)
}
return rr, nil
}
|