Created
December 18, 2017 11:08
-
-
Save sanae10001/9160036d42410618caa76c5e72cb937d to your computer and use it in GitHub Desktop.
A go graceful server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ( | |
"context" | |
"crypto/tls" | |
"log" | |
"net/http" | |
"os" | |
"os/signal" | |
"syscall" | |
"time" | |
"golang.org/x/crypto/acme/autocert" | |
) | |
const ( | |
DefaultWaitShutdown = 10 * time.Second | |
) | |
func ListenAndServe(addr string, h http.Handler) { | |
srv := Default() | |
srv.Addr = addr | |
srv.Handler = h | |
srv.Start() | |
} | |
func ListenAndServeTLS(addr string, h http.Handler, certFile, keyFile string) { | |
srv := Default() | |
srv.Addr = addr | |
srv.Handler = h | |
srv.StartTLS(certFile, keyFile) | |
} | |
func ListenAndServeAutoTLS(addr string, h http.Handler, m *autocert.Manager) { | |
srv := Default() | |
srv.Addr = addr | |
srv.Handler = h | |
srv.StartAutoTLS(m) | |
} | |
func New() *Server { | |
srv := new(Server) | |
srv.Logger = log.New(os.Stderr, "", log.LstdFlags) | |
return srv | |
} | |
func Default() *Server { | |
srv := new(Server) | |
srv.ReadTimeout = 10 * time.Second | |
srv.WriteTimeout = 10 * time.Second | |
srv.MaxHeaderBytes = 1 << 20 // 1M, 2**20 | |
srv.Logger = log.New(os.Stderr, "", log.LstdFlags) | |
srv.WaitShutdown = DefaultWaitShutdown | |
return srv | |
} | |
// A graceful server | |
type Server struct { | |
http.Server | |
// Gracefully shutdown with a timeout. Default 10s | |
WaitShutdown time.Duration | |
// A logger | |
Logger *log.Logger | |
} | |
func (s *Server) logStart() { | |
s.Logger.Printf("Server listening on %s\n", s.Addr) | |
} | |
func (s *Server) Start() { | |
s.logStart() | |
go func() { | |
if err := s.ListenAndServe(); err != nil { | |
log.Fatalln(err) | |
} | |
}() | |
s.graceful() | |
} | |
func (s *Server) StartTLS(certFile, keyFile string) { | |
s.logStart() | |
go func() { | |
if err := s.ListenAndServeTLS(certFile, keyFile); err != nil { | |
log.Fatalln(err) | |
} | |
}() | |
s.graceful() | |
} | |
func (s *Server) StartAutoTLS(m *autocert.Manager) { | |
if m == nil { | |
m = &autocert.Manager{ | |
Prompt: autocert.AcceptTOS, | |
} | |
} | |
s.TLSConfig = &tls.Config{ | |
GetCertificate: m.GetCertificate, | |
} | |
s.StartTLS("", "") | |
} | |
func (s *Server) graceful() { | |
// Wait for interrupt, term, quit signal | |
quit := make(chan os.Signal) | |
signal.Notify(quit, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT) | |
<-quit | |
// Gracefully shutdown with a timeout of 10 seconds. | |
if s.WaitShutdown == 0 { | |
s.WaitShutdown = DefaultWaitShutdown | |
} | |
ctx, cancel := context.WithTimeout(context.Background(), s.WaitShutdown) | |
defer cancel() | |
s.Logger.Printf("Shutting down the server with timeout: %s\n", s.WaitShutdown) | |
if err := s.Shutdown(ctx); err != nil { | |
s.Logger.Fatalln(err) | |
} else { | |
s.Logger.Println("Server gracefully stopped!") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment