diff options
author | Matt Holt <[email protected]> | 2024-12-20 10:55:02 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2024-12-20 10:55:02 -0700 |
commit | 86da4e8f56f3518bc053dd4f68a78c538a4aab5f (patch) | |
tree | baaf259e90a81d56bf8a2999809d396a02fe1ea9 /modules/caddyhttp/app.go | |
parent | 130c868e95dfd1a8b1d39fd217bc6378f6b72ec0 (diff) | |
parent | ed1c594cdbddf89829eaf1174f414028577b432d (diff) | |
download | caddy-86da4e8f56f3518bc053dd4f68a78c538a4aab5f.tar.gz caddy-86da4e8f56f3518bc053dd4f68a78c538a4aab5f.zip |
Merge branch 'master' into transfer-encoding-matchtransfer-encoding-match
Diffstat (limited to 'modules/caddyhttp/app.go')
-rw-r--r-- | modules/caddyhttp/app.go | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/modules/caddyhttp/app.go b/modules/caddyhttp/app.go index 7dc2bee72..850d3aa8f 100644 --- a/modules/caddyhttp/app.go +++ b/modules/caddyhttp/app.go @@ -15,6 +15,7 @@ package caddyhttp import ( + "cmp" "context" "crypto/tls" "fmt" @@ -142,6 +143,10 @@ type App struct { // affect functionality. Servers map[string]*Server `json:"servers,omitempty"` + // If set, metrics observations will be enabled. + // This setting is EXPERIMENTAL and subject to change. + Metrics *Metrics `json:"metrics,omitempty"` + ctx caddy.Context logger *zap.Logger tlsApp *caddytls.TLS @@ -184,6 +189,10 @@ func (app *App) Provision(ctx caddy.Context) error { return err } + if app.Metrics != nil { + app.Metrics.init = sync.Once{} + app.Metrics.httpMetrics = &httpMetrics{} + } // prepare each server oldContext := ctx.Context for srvName, srv := range app.Servers { @@ -196,6 +205,15 @@ func (app *App) Provision(ctx caddy.Context) error { srv.errorLogger = app.logger.Named("log.error") srv.shutdownAtMu = new(sync.RWMutex) + if srv.Metrics != nil { + srv.logger.Warn("per-server 'metrics' is deprecated; use 'metrics' in the root 'http' app instead") + app.Metrics = cmp.Or[*Metrics](app.Metrics, &Metrics{ + init: sync.Once{}, + httpMetrics: &httpMetrics{}, + }) + app.Metrics.PerHost = app.Metrics.PerHost || srv.Metrics.PerHost + } + // only enable access logs if configured if srv.Logs != nil { srv.accessLogger = app.logger.Named("log.access") @@ -342,16 +360,11 @@ func (app *App) Provision(ctx caddy.Context) error { srv.listenerWrappers = append([]caddy.ListenerWrapper{new(tlsPlaceholderWrapper)}, srv.listenerWrappers...) } } - // pre-compile the primary handler chain, and be sure to wrap it in our // route handler so that important security checks are done, etc. primaryRoute := emptyHandler if srv.Routes != nil { - if srv.Metrics != nil { - srv.Metrics.init = sync.Once{} - srv.Metrics.httpMetrics = &httpMetrics{} - } - err := srv.Routes.ProvisionHandlers(ctx, srv.Metrics) + err := srv.Routes.ProvisionHandlers(ctx, app.Metrics) if err != nil { return fmt.Errorf("server %s: setting up route handlers: %v", srvName, err) } @@ -370,7 +383,7 @@ func (app *App) Provision(ctx caddy.Context) error { // provision the named routes (they get compiled at runtime) for name, route := range srv.NamedRoutes { - err := route.Provision(ctx, srv.Metrics) + err := route.Provision(ctx, app.Metrics) if err != nil { return fmt.Errorf("server %s: setting up named route '%s' handlers: %v", name, srvName, err) } @@ -388,6 +401,9 @@ func (app *App) Provision(ctx caddy.Context) error { if srv.IdleTimeout == 0 { srv.IdleTimeout = defaultIdleTimeout } + if srv.ReadHeaderTimeout == 0 { + srv.ReadHeaderTimeout = defaultReadHeaderTimeout // see #6663 + } } ctx.Context = oldContext return nil @@ -689,16 +705,7 @@ func (app *App) Stop() error { return } - // First close h3server then close listeners unlike stdlib for several reasons: - // 1, udp has only a single socket, once closed, no more data can be read and - // written. In contrast, closing tcp listeners won't affect established connections. - // This have something to do with graceful shutdown when upstream implements it. - // 2, h3server will only close listeners it's registered (quic listeners). Closing - // listener first and these listeners maybe unregistered thus won't be closed. caddy - // distinguishes quic-listener and underlying datagram sockets. - - // TODO: CloseGracefully, once implemented upstream (see https://github.com/quic-go/quic-go/issues/2103) - if err := server.h3server.Close(); err != nil { + if err := server.h3server.Shutdown(ctx); err != nil { app.logger.Error("HTTP/3 server shutdown", zap.Error(err), zap.Strings("addresses", server.Listen)) @@ -766,11 +773,20 @@ func (app *App) httpsPort() int { return app.HTTPSPort } -// defaultIdleTimeout is the default HTTP server timeout -// for closing idle connections; useful to avoid resource -// exhaustion behind hungry CDNs, for example (we've had -// several complaints without this). -const defaultIdleTimeout = caddy.Duration(5 * time.Minute) +const ( + // defaultIdleTimeout is the default HTTP server timeout + // for closing idle connections; useful to avoid resource + // exhaustion behind hungry CDNs, for example (we've had + // several complaints without this). + defaultIdleTimeout = caddy.Duration(5 * time.Minute) + + // defaultReadHeaderTimeout is the default timeout for + // reading HTTP headers from clients. Headers are generally + // small, often less than 1 KB, so it shouldn't take a + // long time even on legitimately slow connections or + // busy servers to read it. + defaultReadHeaderTimeout = caddy.Duration(time.Minute) +) // Interface guards var ( |