in banyand/liaison/http/server.go [135:244]
func (p *server) PreRun(_ context.Context) error {
p.l = logger.GetLogger(p.Name())
p.l.Info().Str("level", p.l.GetLevel().String()).Msg("Logger initialized")
// Log flag values after parsing
p.l.Debug().Bool("tls", p.tls).Str("certFile", p.certFile).Str("keyFile", p.keyFile).Msg("Flag values after parsing")
// Initialize TLSReloader if TLS is enabled
p.l.Debug().Bool("tls", p.tls).Msg("HTTP TLS flag is set")
if p.tls {
p.l.Debug().Str("certFile", p.certFile).Str("keyFile", p.keyFile).Msg("Initializing TLSReloader for HTTP")
var err error
p.tlsReloader, err = pkgtls.NewReloader(p.certFile, p.keyFile, p.l)
if err != nil {
p.l.Error().Err(err).Msg("Failed to initialize TLSReloader for HTTP")
return err
}
} else {
p.l.Warn().Msg("HTTP TLS is disabled, skipping TLSReloader initialization")
}
// Initialize gRPC client with cert file
if p.grpcCert != "" {
p.l.Debug().Str("grpcCert", p.grpcCert).Msg("Initializing TLS credentials for gRPC connection")
// Create a client cert reloader that only watches the cert file
var err error
p.grpcTLSReloader, err = pkgtls.NewClientCertReloader(p.grpcCert, p.l)
if err != nil {
p.l.Error().Err(err).Msg("Failed to initialize gRPC TLS reloader")
return err
}
// Start the reloader
if err = p.grpcTLSReloader.Start(); err != nil {
p.l.Error().Err(err).Msg("Failed to start gRPC TLS reloader")
return err
}
// Get the update channel from the reloader
certUpdateCh := p.grpcTLSReloader.GetUpdateChannel()
p.l.Info().Msg("Starting certificate update notification listener")
// Start a goroutine to watch for certificate update events
go func() {
p.l.Info().Msg("Certificate update notification goroutine started")
for {
select {
case <-certUpdateCh:
// Certificate was updated, let's debounce to handle potential multiple notifications
p.l.Info().Msg("Received certificate update notification")
// Debounce multiple notifications that might come in rapid succession
func() {
p.l.Info().Msg("Processing certificate update after debounce")
// Cancel existing gRPC connections
prevGRPCCancel := p.grpcCancel
if prevGRPCCancel != nil {
defer func() {
p.l.Info().Msg("Canceling existing gRPC connections")
prevGRPCCancel()
}()
}
// Create a new context for the new connections
p.grpcCtx, p.grpcCancel = context.WithCancel(context.Background())
// Force a short delay to ensure all resources are properly cleaned up
time.Sleep(200 * time.Millisecond)
// Re-create the gateway with updated credentials
if p.gwMux != nil {
p.l.Info().Msg("Re-creating gateway with updated credentials")
}
// Reinitialize the gRPC client (which will get fresh credentials from the reloader)
if err := p.initGRPCClient(); err != nil {
p.l.Error().Err(err).Msg("Failed to reinitialize gRPC client after credential update")
} else {
p.l.Info().Msg("Successfully reinitialized gRPC client with new credentials")
}
}()
case <-p.stopCh:
p.l.Info().Msg("Stopping certificate update notification listener")
return
}
}
}()
}
p.handlerWrapper = &atomicHandler{}
// Configure the HTTP server with dynamic TLS if enabled
p.srv = &http.Server{
Addr: p.listenAddr,
Handler: p.handlerWrapper,
ReadHeaderTimeout: 3 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 60 * time.Second,
}
if p.tls {
p.srv.TLSConfig = p.tlsReloader.GetTLSConfig()
}
return nil
}