newAdminHandler reads admin's config and returns an http.Handler suitable for use in an admin endpoint server, which will be listening on listenAddr.
(addr NetworkAddress, remote bool, ctx Context)
| 219 | // newAdminHandler reads admin's config and returns an http.Handler suitable |
| 220 | // for use in an admin endpoint server, which will be listening on listenAddr. |
| 221 | func (admin *AdminConfig) newAdminHandler(addr NetworkAddress, remote bool, ctx Context) (adminHandler, error) { |
| 222 | muxWrap := adminHandler{mux: http.NewServeMux()} |
| 223 | |
| 224 | // secure the local or remote endpoint respectively |
| 225 | if remote { |
| 226 | muxWrap.remoteControl = admin.Remote |
| 227 | } else { |
| 228 | // see comment in allowedOrigins() as to why we disable the host check for unix/fd networks |
| 229 | muxWrap.enforceHost = !addr.isWildcardInterface() && !addr.IsUnixNetwork() && !addr.IsFdNetwork() |
| 230 | muxWrap.allowedOrigins = admin.allowedOrigins(addr) |
| 231 | muxWrap.enforceOrigin = admin.EnforceOrigin |
| 232 | } |
| 233 | |
| 234 | addRouteWithMetrics := func(pattern string, handlerLabel string, h http.Handler) { |
| 235 | labels := prometheus.Labels{"path": pattern, "handler": handlerLabel} |
| 236 | h = instrumentHandlerCounter( |
| 237 | adminMetrics.requestCount.MustCurryWith(labels), |
| 238 | h, |
| 239 | ) |
| 240 | muxWrap.mux.Handle(pattern, h) |
| 241 | } |
| 242 | // addRoute just calls muxWrap.mux.Handle after |
| 243 | // wrapping the handler with error handling |
| 244 | addRoute := func(pattern string, handlerLabel string, h AdminHandler) { |
| 245 | wrapper := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 246 | err := h.ServeHTTP(w, r) |
| 247 | if err != nil { |
| 248 | labels := prometheus.Labels{ |
| 249 | "path": pattern, |
| 250 | "handler": handlerLabel, |
| 251 | "method": strings.ToUpper(r.Method), |
| 252 | } |
| 253 | adminMetrics.requestErrors.With(labels).Inc() |
| 254 | } |
| 255 | muxWrap.handleError(w, r, err) |
| 256 | }) |
| 257 | addRouteWithMetrics(pattern, handlerLabel, wrapper) |
| 258 | } |
| 259 | |
| 260 | const handlerLabel = "admin" |
| 261 | |
| 262 | // register standard config control endpoints |
| 263 | addRoute("/"+rawConfigKey+"/", handlerLabel, AdminHandlerFunc(handleConfig)) |
| 264 | addRoute("/id/", handlerLabel, AdminHandlerFunc(handleConfigID)) |
| 265 | addRoute("/stop", handlerLabel, AdminHandlerFunc(handleStop)) |
| 266 | |
| 267 | // register debugging endpoints |
| 268 | addRouteWithMetrics("/debug/pprof/", handlerLabel, http.HandlerFunc(pprof.Index)) |
| 269 | addRouteWithMetrics("/debug/pprof/cmdline", handlerLabel, http.HandlerFunc(pprof.Cmdline)) |
| 270 | addRouteWithMetrics("/debug/pprof/profile", handlerLabel, http.HandlerFunc(pprof.Profile)) |
| 271 | addRouteWithMetrics("/debug/pprof/symbol", handlerLabel, http.HandlerFunc(pprof.Symbol)) |
| 272 | addRouteWithMetrics("/debug/pprof/trace", handlerLabel, http.HandlerFunc(pprof.Trace)) |
| 273 | addRouteWithMetrics("/debug/vars", handlerLabel, expvar.Handler()) |
| 274 | |
| 275 | // register third-party module endpoints |
| 276 | for _, m := range GetModules("admin.api") { |
| 277 | router := m.New().(AdminRouter) |
| 278 |