-
-
Save dstroot/faef20a6c863b5fa8e3438f6055e36cd to your computer and use it in GitHub Desktop.
Revisions
-
Dan Stroot revised this gist
Jan 3, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -15,7 +15,7 @@ func main() { router := newRouter() server := newServer( listenAddr, (middlewares{ logging(logger), tracing(func() string { return fmt.Sprintf("%d", time.Now().UnixNano()) })}).apply(router), logger, ) -
Dan Stroot revised this gist
Jan 8, 2018 . 2 changed files with 4 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -13,14 +13,14 @@ func main() { // create a logger, router and server logger := log.New(os.Stdout, "http: ", log.LstdFlags) router := newRouter() server := newServer( listenAddr, (middlewares{tracing(func() string { return fmt.Sprintf("%d", time.Now().UnixNano()) }), logging(logger)}).apply(router), logger, ) // run our server if err := server.run(); err != nil { log.Fatal(err) } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -22,7 +22,7 @@ type Server struct { } // NewServer creates a new HTTP Server func newServer(port string, h http.Handler, l *log.Logger) *Server { return &Server{ server: &http.Server{ Addr: ":" + port, @@ -37,7 +37,7 @@ func NewServer(port string, h http.Handler, l *log.Logger) *Server { } // Run starts the HTTP server func (s *Server) run() error { // Get hostname hostname, err := os.Hostname() -
Dan Stroot revised this gist
Jan 8, 2018 . 5 changed files with 188 additions and 116 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,31 @@ package main import ( "io" "net/http" "sync/atomic" ) func index() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("Content-Type", "text/plain; charset=utf-8") io.WriteString(w, "Hello, World!") }) } func healthz() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if atomic.LoadInt32(&healthy) == 1 { w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("Content-Type", "application/json; charset=utf-8") io.WriteString(w, `{"alive": true}`) return } w.WriteHeader(http.StatusServiceUnavailable) }) } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,129 +1,26 @@ package main import ( "fmt" "log" "os" "time" ) func main() { listenAddr := "5000" // create a logger, router and server logger := log.New(os.Stdout, "http: ", log.LstdFlags) router := newRouter() server := NewServer( listenAddr, (middlewares{tracing(func() string { return fmt.Sprintf("%d", time.Now().UnixNano()) }), logging(logger)}).apply(router), logger, ) // run our server if err := server.Run(); err != nil { log.Fatal(err) } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,52 @@ package main import ( "context" "log" "net/http" ) type key int const ( requestIDKey key = 0 ) type middleware func(http.Handler) http.Handler type middlewares []middleware func (mws middlewares) apply(hdlr http.Handler) http.Handler { if len(mws) == 0 { return hdlr } return mws[1:].apply(mws[0](hdlr)) } func logging(logger *log.Logger) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { requestID, ok := r.Context().Value(requestIDKey).(string) if !ok { requestID = "unknown" } logger.Println(requestID, r.Method, r.URL.Path, r.RemoteAddr, r.UserAgent()) }() next.ServeHTTP(w, r) }) } } func tracing(nextRequestID func() string) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { requestID := r.Header.Get("X-Request-Id") if requestID == "" { requestID = nextRequestID() } ctx := context.WithValue(r.Context(), requestIDKey, requestID) w.Header().Set("X-Request-Id", requestID) next.ServeHTTP(w, r.WithContext(ctx)) }) } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,15 @@ package main import ( "net/http" ) func newRouter() *http.ServeMux { router := http.NewServeMux() // routes router.Handle("/", index()) router.Handle("/healthz", healthz()) return router } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,77 @@ package main import ( "context" "fmt" "log" "net/http" "os" "os/signal" "sync/atomic" "syscall" "time" ) var ( healthy int32 ) // Server implements our HTTP server type Server struct { server *http.Server } // NewServer creates a new HTTP Server func NewServer(port string, h http.Handler, l *log.Logger) *Server { return &Server{ server: &http.Server{ Addr: ":" + port, Handler: h, // pass in mux/router ErrorLog: l, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 30 * time.Second, MaxHeaderBytes: 1 << 20, }, } } // Run starts the HTTP server func (s *Server) Run() error { // Get hostname hostname, err := os.Hostname() if err != nil { return err } done := make(chan bool) quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) go func() { <-quit fmt.Println("") s.server.ErrorLog.Printf("%s - Shutdown signal received...\n", hostname) atomic.StoreInt32(&healthy, 0) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() s.server.SetKeepAlivesEnabled(false) if err := s.server.Shutdown(ctx); err != nil { s.server.ErrorLog.Fatalf("Could not gracefully shutdown the server: %v\n", err) } close(done) }() s.server.ErrorLog.Printf("%s - Starting server on port %v", hostname, s.server.Addr) atomic.StoreInt32(&healthy, 1) if err := s.server.ListenAndServe(); err != nil && err != http.ErrServerClosed { s.server.ErrorLog.Fatalf("Could not listen on %s: %v\n", s.server.Addr, err) } <-done s.server.ErrorLog.Printf("%s - Server gracefully stopped.\n", hostname) return nil } -
Enrico Foltran revised this gist
Jan 7, 2018 . 1 changed file with 5 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -47,6 +47,7 @@ func main() { IdleTimeout: 15 * time.Second, } done := make(chan bool) quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) @@ -55,21 +56,23 @@ func main() { logger.Println("Server is shutting down...") atomic.StoreInt32(&healthy, 0) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() server.SetKeepAlivesEnabled(false) if err := server.Shutdown(ctx); err != nil { logger.Fatalf("Could not gracefully shutdown the server: %v\n", err) } close(done) }() logger.Println("Server is ready to handle requests at", listenAddr) atomic.StoreInt32(&healthy, 1) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Fatalf("Could not listen on %s: %v\n", listenAddr, err) } <-done logger.Println("Server stopped") } -
Enrico Foltran revised this gist
Jan 7, 2018 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -52,15 +52,15 @@ func main() { go func() { <-quit logger.Println("Server is shutting down...") atomic.StoreInt32(&healthy, 0) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() server.SetKeepAlivesEnabled(false) if err := server.Shutdown(ctx); err != nil { logger.Fatalf("Could not gracefully shutdown the server: %v\n", err) } }() -
Enrico Foltran created this gist
Jan 7, 2018 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,126 @@ package main import ( "context" "flag" "fmt" "log" "net/http" "os" "os/signal" "sync/atomic" "time" ) type key int const ( requestIDKey key = 0 ) var ( listenAddr string healthy int32 ) func main() { flag.StringVar(&listenAddr, "listen-addr", ":5000", "server listen address") flag.Parse() logger := log.New(os.Stdout, "http: ", log.LstdFlags) logger.Println("Server is starting...") router := http.NewServeMux() router.Handle("/", index()) router.Handle("/healthz", healthz()) nextRequestID := func() string { return fmt.Sprintf("%d", time.Now().UnixNano()) } server := &http.Server{ Addr: listenAddr, Handler: tracing(nextRequestID)(logging(logger)(router)), ErrorLog: logger, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 15 * time.Second, } quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) go func() { <-quit logger.Println("Server is shoutting down...") atomic.StoreInt32(&healthy, 0) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() server.SetKeepAlivesEnabled(false) if err := server.Shutdown(ctx); err != nil { logger.Fatalf("Could not gracefully shoutdown the server: %v\n", err) } }() logger.Println("Server is ready to handle requests at", listenAddr) atomic.StoreInt32(&healthy, 1) if err := server.ListenAndServe(); err != http.ErrServerClosed { logger.Fatalf("Could not listen on %s: %v\n", listenAddr, err) } logger.Println("Server stopped") } func index() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.Header().Set("X-Content-Type-Options", "nosniff") w.WriteHeader(http.StatusOK) fmt.Fprintln(w, "Hello, World!") }) } func healthz() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if atomic.LoadInt32(&healthy) == 1 { w.WriteHeader(http.StatusNoContent) return } w.WriteHeader(http.StatusServiceUnavailable) }) } func logging(logger *log.Logger) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { requestID, ok := r.Context().Value(requestIDKey).(string) if !ok { requestID = "unknown" } logger.Println(requestID, r.Method, r.URL.Path, r.RemoteAddr, r.UserAgent()) }() next.ServeHTTP(w, r) }) } } func tracing(nextRequestID func() string) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { requestID := r.Header.Get("X-Request-Id") if requestID == "" { requestID = nextRequestID() } ctx := context.WithValue(r.Context(), requestIDKey, requestID) w.Header().Set("X-Request-Id", requestID) next.ServeHTTP(w, r.WithContext(ctx)) }) } }