@@ -339,6 +339,17 @@ func (web *webAPI) tlsConfigChanged(ctx context.Context, tlsConf *tlsConfigSetti
339339// loggerKeyServer is the key used by [webAPI] to identify servers.
340340const loggerKeyServer = "server"
341341
342+ // getBindAddr returns the address string for the server to listen on. If the
343+ // address is unspecified, it returns the ":port" format to enable dual-stack
344+ // listening.
345+ func (web * webAPI ) getBindAddr (addr netip.Addr , port uint16 ) (addrStr string ) {
346+ if addr .IsUnspecified () {
347+ return netutil .JoinHostPort ("" , port )
348+ }
349+
350+ return netip .AddrPortFrom (addr , port ).String ()
351+ }
352+
342353// start starts serving HTTP requests.
343354func (web * webAPI ) start (ctx context.Context ) {
344355 defer slogutil .RecoverAndExit (ctx , web .logger , osutil .ExitCodeFailure )
@@ -363,7 +374,7 @@ func (web *webAPI) start(ctx context.Context) {
363374
364375 // Create a new instance, because the Web is not usable after Shutdown.
365376 web .httpServer = & http.Server {
366- Addr : web .conf .BindAddr .String ( ),
377+ Addr : web .getBindAddr ( web . conf .BindAddr .Addr (), web . conf . BindAddr . Port () ),
367378 Handler : hdlr ,
368379 ReadTimeout : web .conf .ReadTimeout ,
369380 ReadHeaderTimeout : web .conf .ReadHeaderTimeout ,
@@ -457,13 +468,13 @@ func (web *webAPI) serveTLS(ctx context.Context) (next bool) {
457468 portHTTPS = config .TLS .PortHTTPS
458469 }()
459470
460- addr := netip . AddrPortFrom (web .conf .BindAddr .Addr (), portHTTPS ). String ( )
471+ addrStr := web . getBindAddr (web .conf .BindAddr .Addr (), portHTTPS )
461472 logger := web .baseLogger .With (loggerKeyServer , "https" )
462473
463474 hdlr := web .wrapMux (logger )
464475
465476 web .httpsServer .server = & http.Server {
466- Addr : addr ,
477+ Addr : addrStr ,
467478 Handler : hdlr ,
468479 TLSConfig : & tls.Config {
469480 Certificates : []tls.Certificate {web .httpsServer .certificate ()},
@@ -480,7 +491,7 @@ func (web *webAPI) serveTLS(ctx context.Context) (next bool) {
480491 printHTTPAddresses (ctx , web .logger , urlutil .SchemeHTTPS , web .tlsManager )
481492
482493 if web .conf .serveHTTP3 {
483- go web .mustStartHTTP3 (ctx , addr )
494+ go web .mustStartHTTP3 (ctx , addrStr )
484495 }
485496
486497 logger .InfoContext (ctx , "starting https server" )
@@ -523,10 +534,9 @@ func (web *webAPI) mustStartHTTP3(ctx context.Context, address string) {
523534 }
524535}
525536
526- // startPprof launches the debug and profiling server on the provided port.
537+ // startPprof launches the debug and profiling server on the provided port on
538+ // both IPv4 and IPv6 loopback addresses.
527539func startPprof (baseLogger * slog.Logger , port uint16 ) {
528- addr := netip .AddrPortFrom (netutil .IPv4Localhost (), port )
529-
530540 runtime .SetBlockProfileRate (1 )
531541 runtime .SetMutexProfileFraction (1 )
532542
@@ -536,15 +546,26 @@ func startPprof(baseLogger *slog.Logger, port uint16) {
536546 ctx := context .Background ()
537547 logger := baseLogger .With (slogutil .KeyPrefix , "pprof" )
538548
539- go func () {
540- defer slogutil .RecoverAndLog (ctx , logger )
549+ go servePprof (ctx , logger , mux , netutil .IPv4Localhost (), port )
550+ go servePprof (ctx , logger , mux , netutil .IPv6Localhost (), port )
551+ }
541552
542- logger .InfoContext (ctx , "listening" , "addr" , addr )
543- err := http .ListenAndServe (addr .String (), mux )
544- if ! errors .Is (err , http .ErrServerClosed ) {
545- logger .ErrorContext (ctx , "shutting down" , slogutil .KeyError , err )
546- }
547- }()
553+ // servePprof serves the pprof HTTP endpoints on the given host and port.
554+ func servePprof (
555+ ctx context.Context ,
556+ logger * slog.Logger ,
557+ mux * http.ServeMux ,
558+ host netip.Addr ,
559+ port uint16 ,
560+ ) {
561+ defer slogutil .RecoverAndLog (ctx , logger )
562+
563+ addrStr := netip .AddrPortFrom (host , port ).String ()
564+ logger .InfoContext (ctx , "listening" , "addr" , addrStr )
565+ err := http .ListenAndServe (addrStr , mux )
566+ if ! errors .Is (err , http .ErrServerClosed ) {
567+ logger .ErrorContext (ctx , "shutting down" , slogutil .KeyError , err )
568+ }
548569}
549570
550571// registerTLSHandlers registers HTTP handlers for TLS configuration.
0 commit comments