[bugfix] shut down LE server nicely (#3714)

* [bugfix] shut down LE server nicely
This commit is contained in:
tobi 2025-01-31 13:45:39 +01:00 committed by GitHub
parent b9e0689359
commit 8a9422aa78
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -48,6 +48,7 @@
type Router struct { type Router struct {
engine *gin.Engine engine *gin.Engine
srv *http.Server srv *http.Server
leSrv *http.Server
} }
// New returns a new Router, which wraps // New returns a new Router, which wraps
@ -185,15 +186,38 @@ func (r *Router) Start() error {
// Stop shuts down the router nicely. // Stop shuts down the router nicely.
func (r *Router) Stop() error { func (r *Router) Stop() error {
log.Infof(nil, "shutting down http router with %s grace period", shutdownTimeout) ctx := context.Background()
timeout, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
defer cancel()
if err := r.srv.Shutdown(timeout); err != nil { // Shut down "main" server.
return fmt.Errorf("error shutting down http router: %s", err) if err := stopServer(ctx, r.srv, "http server"); err != nil {
return err
} }
log.Info(nil, "http router closed connections and shut down gracefully") // Shut down letsencrypt
// server if enabled.
if r.leSrv != nil {
if err := stopServer(ctx, r.leSrv, "letsencrypt http server"); err != nil {
return err
}
}
return nil
}
func stopServer(
ctx context.Context,
s *http.Server,
name string,
) error {
timeout, cancel := context.WithTimeout(ctx, shutdownTimeout)
defer cancel()
log.Infof(nil, "shutting down %s with %s grace period", name, shutdownTimeout)
if err := s.Shutdown(timeout); err != nil {
return fmt.Errorf("error shutting down %s: %w", name, err)
}
log.Infof(ctx, "%s closed connections and shut down gracefully", name)
return nil return nil
} }
@ -228,8 +252,8 @@ func (r *Router) customTLS(
// letsEncryptTLS modifies the router's underlying http // letsEncryptTLS modifies the router's underlying http
// server to use LetsEncrypt via an ACME Autocert manager. // server to use LetsEncrypt via an ACME Autocert manager.
// //
// It also starts a listener on the configured LetsEncrypt // It also sets r.leSrv and starts a listener on the
// port to validate LE requests. // configured LetsEncrypt port to validate LE requests.
func (r *Router) letsEncryptTLS() (func() error, error) { func (r *Router) letsEncryptTLS() (func() error, error) {
acm := &autocert.Manager{ acm := &autocert.Manager{
Prompt: autocert.AcceptTOS, Prompt: autocert.AcceptTOS,
@ -261,17 +285,18 @@ func (r *Router) letsEncryptTLS() (func() error, error) {
// Take our own copy of the HTTP server, // Take our own copy of the HTTP server,
// and update it to serve LetsEncrypt // and update it to serve LetsEncrypt
// requests via the autocert manager. // requests via the autocert manager.
leSrv := (*r.srv) //nolint:govet r.leSrv = new(http.Server) //nolint:gosec
leSrv.Handler = acm.HTTPHandler(fallback) *r.leSrv = (*r.srv) //nolint:govet
leSrv.Addr = fmt.Sprintf("%s:%d", r.leSrv.Handler = acm.HTTPHandler(fallback)
r.leSrv.Addr = fmt.Sprintf("%s:%d",
config.GetBindAddress(), config.GetBindAddress(),
config.GetLetsEncryptPort(), config.GetLetsEncryptPort(),
) )
go func() { go func() {
// Start the LetsEncrypt autocert manager HTTP server. // Start the LetsEncrypt autocert manager HTTP server.
log.Infof(nil, "letsencrypt listening on %s", leSrv.Addr) log.Infof(nil, "letsencrypt listening on %s", r.leSrv.Addr)
if err := leSrv.ListenAndServe(); err != nil && if err := r.leSrv.ListenAndServe(); err != nil &&
err != http.ErrServerClosed { err != http.ErrServerClosed {
log.Panicf(nil, "letsencrypt: listen: %v", err) log.Panicf(nil, "letsencrypt: listen: %v", err)
} }