mirror of
https://github.com/therootcompany/golib.git
synced 2026-11-04 06:55:00 +00:00
feat(form2mail): graceful SIGTERM shutdown via http.Server.Shutdown
log.Fatal(http.ListenAndServe) ignores ctx cancellation, so SIGTERM from systemd hung the process until TimeoutStopSec (90s) triggered SIGKILL. Replace with explicit *http.Server + Shutdown(ctx) driven by the existing signal.NotifyContext ctx so restarts complete in under a second.
This commit is contained in:
parent
4ab9ffe364
commit
6a85a93605
@ -263,10 +263,10 @@ func main() {
|
|||||||
fmt.Fprintf(os.Stderr, "%s\n", time.Since(tGeo).Round(time.Millisecond))
|
fmt.Fprintf(os.Stderr, "%s\n", time.Since(tGeo).Round(time.Millisecond))
|
||||||
|
|
||||||
fm := &formmailer.FormMailer{
|
fm := &formmailer.FormMailer{
|
||||||
SMTPHost: cfg.smtpHost,
|
SMTPHost: cfg.smtpHost,
|
||||||
SMTPFrom: cfg.smtpFrom,
|
SMTPFrom: cfg.smtpFrom,
|
||||||
SMTPTo: strings.Split(cfg.smtpToList, ","),
|
SMTPTo: strings.Split(cfg.smtpToList, ","),
|
||||||
SMTPUser: cfg.smtpUser,
|
SMTPUser: cfg.smtpUser,
|
||||||
SMTPPass: cfg.smtpPass,
|
SMTPPass: cfg.smtpPass,
|
||||||
Subject: cfg.smtpSubject,
|
Subject: cfg.smtpSubject,
|
||||||
SuccessBody: successBody, // fallback if read fails
|
SuccessBody: successBody, // fallback if read fails
|
||||||
@ -276,8 +276,8 @@ func main() {
|
|||||||
// Legacy behavior: bot/blacklist rejections render {.SupportEmail}
|
// Legacy behavior: bot/blacklist rejections render {.SupportEmail}
|
||||||
// as "[REDACTED]" rather than leaving it blank.
|
// as "[REDACTED]" rather than leaving it blank.
|
||||||
HiddenSupportValue: "[REDACTED]",
|
HiddenSupportValue: "[REDACTED]",
|
||||||
Blacklist: blacklist,
|
Blacklist: blacklist,
|
||||||
Geo: geo,
|
Geo: geo,
|
||||||
// North America + unknown. Unknown ("") is always allowed by formmailer.
|
// North America + unknown. Unknown ("") is always allowed by formmailer.
|
||||||
AllowedCountries: []string{"US", "CA", "MX", "CR", "VI"},
|
AllowedCountries: []string{"US", "CA", "MX", "CR", "VI"},
|
||||||
Fields: []formmailer.Field{
|
Fields: []formmailer.Field{
|
||||||
@ -301,19 +301,43 @@ func main() {
|
|||||||
log.Printf("geoip refresh: %v", err)
|
log.Printf("geoip refresh: %v", err)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
mux := http.NewServeMux()
|
||||||
contact := silentDropRU(fm, successBody, cfg.responseType)
|
contact := silentDropRU(fm, successBody, cfg.responseType)
|
||||||
http.Handle("POST /contact", contact)
|
mux.Handle("POST /contact", contact)
|
||||||
http.Handle("POST /contact/", contact)
|
mux.Handle("POST /contact/", contact)
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
_, _ = fmt.Fprintln(w, "form2email server running. POST form data to /contact")
|
_, _ = fmt.Fprintln(w, "form2email server running. POST form data to /contact")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
srv := &http.Server{Addr: cfg.listenAddr, Handler: mux}
|
||||||
|
|
||||||
fmt.Printf("form2email listening on http://%s\n", cfg.listenAddr)
|
fmt.Printf("form2email listening on http://%s\n", cfg.listenAddr)
|
||||||
fmt.Printf("Forwarding submissions from %s → %s via %s\n", cfg.smtpFrom, cfg.smtpToList, cfg.smtpHost)
|
fmt.Printf("Forwarding submissions from %s → %s via %s\n", cfg.smtpFrom, cfg.smtpToList, cfg.smtpHost)
|
||||||
fmt.Printf("Rate limit: ~%d req/min per IP (burst %d)\n", requestsPerMinute, burstSize)
|
fmt.Printf("Rate limit: ~%d req/min per IP (burst %d)\n", requestsPerMinute, burstSize)
|
||||||
fmt.Println("CTRL+C to stop")
|
fmt.Println("CTRL+C to stop")
|
||||||
|
|
||||||
log.Fatal(http.ListenAndServe(cfg.listenAddr, nil))
|
serveErr := make(chan error, 1)
|
||||||
|
go func() {
|
||||||
|
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
|
serveErr <- err
|
||||||
|
}
|
||||||
|
close(serveErr)
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.Printf("shutdown: %v", ctx.Err())
|
||||||
|
case err := <-serveErr:
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("listen: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
if err := srv.Shutdown(shutdownCtx); err != nil {
|
||||||
|
log.Printf("shutdown: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// silentDropRU returns a handler that silently returns the success body for
|
// silentDropRU returns a handler that silently returns the success body for
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user