Skip to content

Commit

Permalink
caddyhttp: Close http3 server gracefully (#6213)
Browse files Browse the repository at this point in the history
* close http3 server gracefully

* update server field

* update from upstream

---------

Co-authored-by: Matt Holt <[email protected]>
  • Loading branch information
WeidiDeng and mholt authored Oct 16, 2024
1 parent a211c65 commit c6f2979
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 33 deletions.
11 changes: 1 addition & 10 deletions modules/caddyhttp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -689,16 +689,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))
Expand Down
24 changes: 1 addition & 23 deletions modules/caddyhttp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,32 +614,14 @@ func (s *Server) serveHTTP3(addr caddy.NetworkAddress, tlsCfg *tls.Config) error
// create HTTP/3 server if not done already
if s.h3server == nil {
s.h3server = &http3.Server{
// Currently when closing a http3.Server, only listeners are closed. But caddy reuses these listeners
// if possible, requests are still read and handled by the old handler. Close these connections manually.
// see issue: https://github.com/caddyserver/caddy/issues/6195
// Will interrupt ongoing requests.
// TODO: remove the handler wrap after http3.Server.CloseGracefully is implemented, see App.Stop
Handler: http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
select {
case <-s.ctx.Done():
if quicConn, ok := request.Context().Value(quicConnCtxKey).(quic.Connection); ok {
//nolint:errcheck
quicConn.CloseWithError(quic.ApplicationErrorCode(http3.ErrCodeRequestRejected), "")
}
default:
s.ServeHTTP(writer, request)
}
}),
Handler: s,
TLSConfig: tlsCfg,
MaxHeaderBytes: s.MaxHeaderBytes,
QUICConfig: &quic.Config{
Versions: []quic.Version{quic.Version1, quic.Version2},
Tracer: qlog.DefaultConnectionTracer,
},
IdleTimeout: time.Duration(s.IdleTimeout),
ConnContext: func(ctx context.Context, c quic.Connection) context.Context {
return context.WithValue(ctx, quicConnCtxKey, c)
},
}
}

Expand Down Expand Up @@ -1099,10 +1081,6 @@ const (
// For referencing underlying net.Conn
ConnCtxKey caddy.CtxKey = "conn"

// For referencing underlying quic.Connection
// TODO: export if needed later
quicConnCtxKey caddy.CtxKey = "quic_conn"

// For tracking whether the client is a trusted proxy
TrustedProxyVarKey string = "trusted_proxy"

Expand Down

0 comments on commit c6f2979

Please sign in to comment.