-
Star
(139)
You must be signed in to star a gist -
Fork
(35)
You must be signed in to fork a gist
-
-
Save peterhellberg/38117e546c217960747aacf689af3dc2 to your computer and use it in GitHub Desktop.
| package main | |
| import ( | |
| "context" | |
| "log" | |
| "net/http" | |
| "os" | |
| "os/signal" | |
| "time" | |
| ) | |
| type Server struct { | |
| logger *log.Logger | |
| mux *http.ServeMux | |
| } | |
| func NewServer(options ...func(*Server)) *Server { | |
| s := &Server{ | |
| logger: log.New(os.Stdout, "", 0), | |
| mux: http.NewServeMux(), | |
| } | |
| for _, f := range options { | |
| f(s) | |
| } | |
| s.mux.HandleFunc("/", s.index) | |
| return s | |
| } | |
| func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |
| s.mux.ServeHTTP(w, r) | |
| } | |
| func (s *Server) index(w http.ResponseWriter, r *http.Request) { | |
| s.logger.Println("GET /") | |
| w.Write([]byte("Hello, World!")) | |
| } | |
| func main() { | |
| stop := make(chan os.Signal, 1) | |
| signal.Notify(stop, os.Interrupt) | |
| logger := log.New(os.Stdout, "", 0) | |
| addr := ":" + os.Getenv("PORT") | |
| if addr == ":" { | |
| addr = ":2017" | |
| } | |
| s := NewServer(func(s *Server) { s.logger = logger }) | |
| h := &http.Server{Addr: addr, Handler: s} | |
| go func() { | |
| logger.Printf("Listening on http://0.0.0.0%s\n", addr) | |
| if err := h.ListenAndServe(); err != nil { | |
| logger.Fatal(err) | |
| } | |
| }() | |
| <-stop | |
| logger.Println("\nShutting down the server...") | |
| ctx, _ := context.WithTimeout(context.Background(), 5*time.Second) | |
| h.Shutdown(ctx) | |
| logger.Println("Server gracefully stopped") | |
| } |
Hi, great contribution.
There is one thing that could make it more complete in my opinion.
Everywhere this code is, it will always print "Listening on http://...." in the console, even if ListenAndServe() was unable to start actually listening.
log.Printf("Listening on http://0.0.0.0%s\n", hs.Addr)
if err := hs.ListenAndServe(); err != http.ErrServerClosed {
log.Fatal(err)
}If you start 1 server, you'll see this in the console:
Listening on http://0.0.0.0:2017If you start a 2nd server without shutting down the 1st one, you will see this in the console:
Listening on http://0.0.0.0:2017
panic... listen tcp :2017: bind: address already in useSo it first shows "Listening on http://..." however this never actually happened.
I'm not a go expert, is there a way to implement this?
-- UPDATE
Apparently using http.Listen and http.Serve individually, it is possible to catch a port in use error (or any other error while trying to listen to a tcp network) before assuming the server is listening.
Source: https://stackoverflow.com/a/48250354/194630
listener, err := net.Listen("tcp", ":"+config.Port)
if err != nil {
log.Fatal(err)
}
done := make(chan bool)
go server.Serve(listener)
// Log server started
log.Printf("Server started at port %v", config.Port)
<-done
@peterhellberg Thanks for sharing this!