Move the tty related logic into pkg utils
- commit
- 7caefd03d8ae5725c353631f557c1e0983975c1b
- author
- bnema · · 2023-09-04 12:52 UTC
- parent
- 090f2a0
- signature
- unsigned
4 files · +134 -53
M cmd/main.go +3 -53
| @@ -1,12 +1,7 @@ | |||
| 1 | 1 | package main | |
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | - | "net/http" | |
| 5 | 4 | "os" | |
| 6 | - | "os/exec" | |
| 7 | - | "os/signal" | |
| 8 | - | "syscall" | |
| 9 | - | "time" | |
| 10 | 5 | ||
| 11 | 6 | "github.com/labstack/echo/v4" | |
| 12 | 7 | "gogs.bnema.dev/gordon-echo/internal/app" | |
| @@ -15,18 +10,6 @@ import ( | |||
| 15 | 10 | "gogs.bnema.dev/gordon-echo/pkg/utils" | |
| 16 | 11 | ) | |
| 17 | 12 | ||
| 18 | - | func setRawMode() { | |
| 19 | - | cmd := exec.Command("stty", "raw", "-echo") | |
| 20 | - | cmd.Stdin = os.Stdin | |
| 21 | - | _ = cmd.Run() | |
| 22 | - | } | |
| 23 | - | ||
| 24 | - | func restoreTerminal() { | |
| 25 | - | cmd := exec.Command("stty", "-raw", "echo") | |
| 26 | - | cmd.Stdin = os.Stdin | |
| 27 | - | _ = cmd.Run() | |
| 28 | - | } | |
| 29 | - | ||
| 30 | 13 | func main() { | |
| 31 | 14 | // Port = os.Getenv("PORT") or fallback to default port (1323) | |
| 32 | 15 | port := os.Getenv("PORT") | |
| @@ -50,42 +33,9 @@ func main() { | |||
| 50 | 33 | e.Logger = utils.NewEchoLoggerWrapper(gordon.APPLogger) | |
| 51 | 34 | e = routes.ConfigureRouter(e, gordon) | |
| 52 | 35 | ||
| 53 | - | // Start the server in a separate goroutine | |
| 54 | - | go func() { | |
| 36 | + | startFunc := func() error { | |
| 55 | 37 | gordon.APPLogger.Info().Msgf("Server is listening on port %s", port) | |
| 56 | - | if err := e.Start(":" + port); err != nil && err != http.ErrServerClosed { | |
| 57 | - | gordon.APPLogger.Fatal().Err(err).Msg("Failed to start the server") | |
| 58 | - | } | |
| 59 | - | }() | |
| 60 | - | ||
| 61 | - | // Catch SIGINT and SIGTERM signals without raw mode initially | |
| 62 | - | c := make(chan os.Signal, 1) | |
| 63 | - | signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) | |
| 64 | - | <-c | |
| 65 | - | ||
| 66 | - | gordon.APPLogger.Warn().Msg("Graceful shutdown initiated") | |
| 67 | - | gordon.APPLogger.Warn().Msg("Server will shutdown in 5 seconds press ENTER to cancel") | |
| 68 | - | ||
| 69 | - | // Now, set raw mode | |
| 70 | - | setRawMode() | |
| 71 | - | defer restoreTerminal() // Ensure terminal is restored even if program exits unexpectedly | |
| 72 | - | ||
| 73 | - | // Channel to signal a key press | |
| 74 | - | keypress := make(chan struct{}) | |
| 75 | - | ||
| 76 | - | // Goroutine to listen for a key press | |
| 77 | - | go func() { | |
| 78 | - | var b []byte = make([]byte, 1) | |
| 79 | - | os.Stdin.Read(b) | |
| 80 | - | keypress <- struct{}{} | |
| 81 | - | }() | |
| 82 | - | ||
| 83 | - | // Wait for either a key press or the 5-second timer | |
| 84 | - | select { | |
| 85 | - | case <-time.After(5 * time.Second): | |
| 86 | - | gordon.APPLogger.Info().Msg("Server shutdown") | |
| 87 | - | case <-keypress: | |
| 88 | - | gordon.APPLogger.Info().Msg("Shutdown cancelled by user") | |
| 38 | + | return e.Start(":" + port) | |
| 89 | 39 | } | |
| 90 | - | ||
| 40 | + | utils.RunAppCatchSIGINT(startFunc, &gordon.APPLogger.Logger) | |
| 91 | 41 | } | |
| @@ -1,12 +1,7 @@ | |||||
| 1 | package main | 1 | package main | ||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | - | "net/http" | |||
| 5 | "os" | 4 | "os" | ||
| 6 | - | "os/exec" | |||
| 7 | - | "os/signal" | |||
| 8 | - | "syscall" | |||
| 9 | - | "time" | |||
| 10 | 5 | ||||
| 11 | "github.com/labstack/echo/v4" | 6 | "github.com/labstack/echo/v4" | ||
| 12 | "gogs.bnema.dev/gordon-echo/internal/app" | 7 | "gogs.bnema.dev/gordon-echo/internal/app" | ||
| @@ -15,18 +10,6 @@ import ( | |||||
| 15 | "gogs.bnema.dev/gordon-echo/pkg/utils" | 10 | "gogs.bnema.dev/gordon-echo/pkg/utils" | ||
| 16 | ) | 11 | ) | ||
| 17 | 12 | ||||
| 18 | - | func setRawMode() { | |||
| 19 | - | cmd := exec.Command("stty", "raw", "-echo") | |||
| 20 | - | cmd.Stdin = os.Stdin | |||
| 21 | - | _ = cmd.Run() | |||
| 22 | - | } | |||
| 23 | - | ||||
| 24 | - | func restoreTerminal() { | |||
| 25 | - | cmd := exec.Command("stty", "-raw", "echo") | |||
| 26 | - | cmd.Stdin = os.Stdin | |||
| 27 | - | _ = cmd.Run() | |||
| 28 | - | } | |||
| 29 | - | ||||
| 30 | func main() { | 13 | func main() { | ||
| 31 | // Port = os.Getenv("PORT") or fallback to default port (1323) | 14 | // Port = os.Getenv("PORT") or fallback to default port (1323) | ||
| 32 | port := os.Getenv("PORT") | 15 | port := os.Getenv("PORT") | ||
| @@ -50,42 +33,9 @@ func main() { | |||||
| 50 | e.Logger = utils.NewEchoLoggerWrapper(gordon.APPLogger) | 33 | e.Logger = utils.NewEchoLoggerWrapper(gordon.APPLogger) | ||
| 51 | e = routes.ConfigureRouter(e, gordon) | 34 | e = routes.ConfigureRouter(e, gordon) | ||
| 52 | 35 | ||||
| 53 | - | // Start the server in a separate goroutine | 36 | + | startFunc := func() error { |
| 54 | - | go func() { | |||
| 55 | gordon.APPLogger.Info().Msgf("Server is listening on port %s", port) | 37 | gordon.APPLogger.Info().Msgf("Server is listening on port %s", port) | ||
| 56 | - | if err := e.Start(":" + port); err != nil && err != http.ErrServerClosed { | 38 | + | return e.Start(":" + port) |
| 57 | - | gordon.APPLogger.Fatal().Err(err).Msg("Failed to start the server") | |||
| 58 | - | } | |||
| 59 | - | }() | |||
| 60 | - | ||||
| 61 | - | // Catch SIGINT and SIGTERM signals without raw mode initially | |||
| 62 | - | c := make(chan os.Signal, 1) | |||
| 63 | - | signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) | |||
| 64 | - | <-c | |||
| 65 | - | ||||
| 66 | - | gordon.APPLogger.Warn().Msg("Graceful shutdown initiated") | |||
| 67 | - | gordon.APPLogger.Warn().Msg("Server will shutdown in 5 seconds press ENTER to cancel") | |||
| 68 | - | ||||
| 69 | - | // Now, set raw mode | |||
| 70 | - | setRawMode() | |||
| 71 | - | defer restoreTerminal() // Ensure terminal is restored even if program exits unexpectedly | |||
| 72 | - | ||||
| 73 | - | // Channel to signal a key press | |||
| 74 | - | keypress := make(chan struct{}) | |||
| 75 | - | ||||
| 76 | - | // Goroutine to listen for a key press | |||
| 77 | - | go func() { | |||
| 78 | - | var b []byte = make([]byte, 1) | |||
| 79 | - | os.Stdin.Read(b) | |||
| 80 | - | keypress <- struct{}{} | |||
| 81 | - | }() | |||
| 82 | - | ||||
| 83 | - | // Wait for either a key press or the 5-second timer | |||
| 84 | - | select { | |||
| 85 | - | case <-time.After(5 * time.Second): | |||
| 86 | - | gordon.APPLogger.Info().Msg("Server shutdown") | |||
| 87 | - | case <-keypress: | |||
| 88 | - | gordon.APPLogger.Info().Msg("Shutdown cancelled by user") | |||
| 89 | } | 39 | } | ||
| 90 | - | 40 | + | utils.RunAppCatchSIGINT(startFunc, &gordon.APPLogger.Logger) | |
| 91 | } | 41 | } | ||
M logs/app.log +19 -0
| @@ -28,3 +28,22 @@ | |||
| 28 | 28 | {"level":"warn","time":"2023-09-04T12:40:12+02:00","message":"Graceful shutdown initiated"} | |
| 29 | 29 | {"level":"warn","time":"2023-09-04T12:40:12+02:00","message":"Server will shutdown in 5 seconds press ENTER to cancel"} | |
| 30 | 30 | {"level":"info","time":"2023-09-04T12:40:17+02:00","message":"Server shutdown"} | |
| 31 | + | {"level":"info","time":"2023-09-04T14:05:05+02:00","message":"Server is listening on port 1323"} | |
| 32 | + | {"level":"info","time":"2023-09-04T14:05:15+02:00","message":"Server is listening on port 1323"} | |
| 33 | + | {"level":"info","time":"2023-09-04T14:39:43+02:00","message":"Server is listening on port 1323"} | |
| 34 | + | {"level":"info","time":"2023-09-04T14:39:43+02:00","message":"Server is listening on port 1323"} | |
| 35 | + | {"level":"fatal","error":"listen tcp :1323: bind: address already in use","time":"2023-09-04T14:39:43+02:00","message":"Failed to start the server"} | |
| 36 | + | {"level":"info","time":"2023-09-04T14:42:19+02:00","message":"Server is listening on port 1323"} | |
| 37 | + | {"level":"info","time":"2023-09-04T14:42:19+02:00","message":"Server is listening on port 1323"} | |
| 38 | + | {"level":"fatal","error":"listen tcp :1323: bind: address already in use","time":"2023-09-04T14:42:19+02:00","message":"Failed to start the server"} | |
| 39 | + | {"level":"info","time":"2023-09-04T14:45:00+02:00","message":"Server is listening on port 1323"} | |
| 40 | + | {"level":"info","time":"2023-09-04T14:45:00+02:00","message":"Server is listening on port 1323"} | |
| 41 | + | {"level":"fatal","error":"listen tcp :1323: bind: address already in use","time":"2023-09-04T14:45:00+02:00","message":"Failed to start the server"} | |
| 42 | + | {"level":"info","time":"2023-09-04T14:50:37+02:00","message":"Server is listening on port 1323"} | |
| 43 | + | {"level":"info","time":"2023-09-04T14:50:37+02:00","message":"Server is listening on port 1323"} | |
| 44 | + | {"level":"fatal","error":"listen tcp :1323: bind: address already in use","time":"2023-09-04T14:50:37+02:00","message":"Failed to start the server"} | |
| 45 | + | {"level":"info","time":"2023-09-04T14:50:51+02:00","message":"Server is listening on port 1323"} | |
| 46 | + | {"level":"info","time":"2023-09-04T14:51:08+02:00","message":"Server is listening on port 1323"} | |
| 47 | + | {"level":"warn","time":"2023-09-04T14:51:10+02:00","message":"Graceful shutdown initiated"} | |
| 48 | + | {"level":"warn","time":"2023-09-04T14:51:10+02:00","message":"Server will shutdown in 5 seconds press ENTER to cancel"} | |
| 49 | + | {"level":"info","time":"2023-09-04T14:51:15+02:00","message":"Server shutdown"} | |
| @@ -28,3 +28,22 @@ | |||||
| 28 | {"level":"warn","time":"2023-09-04T12:40:12+02:00","message":"Graceful shutdown initiated"} | 28 | {"level":"warn","time":"2023-09-04T12:40:12+02:00","message":"Graceful shutdown initiated"} | ||
| 29 | {"level":"warn","time":"2023-09-04T12:40:12+02:00","message":"Server will shutdown in 5 seconds press ENTER to cancel"} | 29 | {"level":"warn","time":"2023-09-04T12:40:12+02:00","message":"Server will shutdown in 5 seconds press ENTER to cancel"} | ||
| 30 | {"level":"info","time":"2023-09-04T12:40:17+02:00","message":"Server shutdown"} | 30 | {"level":"info","time":"2023-09-04T12:40:17+02:00","message":"Server shutdown"} | ||
| 31 | + | {"level":"info","time":"2023-09-04T14:05:05+02:00","message":"Server is listening on port 1323"} | |||
| 32 | + | {"level":"info","time":"2023-09-04T14:05:15+02:00","message":"Server is listening on port 1323"} | |||
| 33 | + | {"level":"info","time":"2023-09-04T14:39:43+02:00","message":"Server is listening on port 1323"} | |||
| 34 | + | {"level":"info","time":"2023-09-04T14:39:43+02:00","message":"Server is listening on port 1323"} | |||
| 35 | + | {"level":"fatal","error":"listen tcp :1323: bind: address already in use","time":"2023-09-04T14:39:43+02:00","message":"Failed to start the server"} | |||
| 36 | + | {"level":"info","time":"2023-09-04T14:42:19+02:00","message":"Server is listening on port 1323"} | |||
| 37 | + | {"level":"info","time":"2023-09-04T14:42:19+02:00","message":"Server is listening on port 1323"} | |||
| 38 | + | {"level":"fatal","error":"listen tcp :1323: bind: address already in use","time":"2023-09-04T14:42:19+02:00","message":"Failed to start the server"} | |||
| 39 | + | {"level":"info","time":"2023-09-04T14:45:00+02:00","message":"Server is listening on port 1323"} | |||
| 40 | + | {"level":"info","time":"2023-09-04T14:45:00+02:00","message":"Server is listening on port 1323"} | |||
| 41 | + | {"level":"fatal","error":"listen tcp :1323: bind: address already in use","time":"2023-09-04T14:45:00+02:00","message":"Failed to start the server"} | |||
| 42 | + | {"level":"info","time":"2023-09-04T14:50:37+02:00","message":"Server is listening on port 1323"} | |||
| 43 | + | {"level":"info","time":"2023-09-04T14:50:37+02:00","message":"Server is listening on port 1323"} | |||
| 44 | + | {"level":"fatal","error":"listen tcp :1323: bind: address already in use","time":"2023-09-04T14:50:37+02:00","message":"Failed to start the server"} | |||
| 45 | + | {"level":"info","time":"2023-09-04T14:50:51+02:00","message":"Server is listening on port 1323"} | |||
| 46 | + | {"level":"info","time":"2023-09-04T14:51:08+02:00","message":"Server is listening on port 1323"} | |||
| 47 | + | {"level":"warn","time":"2023-09-04T14:51:10+02:00","message":"Graceful shutdown initiated"} | |||
| 48 | + | {"level":"warn","time":"2023-09-04T14:51:10+02:00","message":"Server will shutdown in 5 seconds press ENTER to cancel"} | |||
| 49 | + | {"level":"info","time":"2023-09-04T14:51:15+02:00","message":"Server shutdown"} | |||
M logs/http.log +47 -0
| @@ -18,3 +18,50 @@ | |||
| 18 | 18 | {"level":"info","type":"http","remote_ip":"::1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T11:57:48+02:00","message":"request"} | |
| 19 | 19 | {"level":"info","type":"http","remote_ip":"::1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T11:57:48+02:00","message":"request"} | |
| 20 | 20 | {"level":"info","type":"http","remote_ip":"::1","method":"GET","URI":"/favicon.ico","status":200,"time":"2023-09-04T11:57:48+02:00","message":"request"} | |
| 21 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/admin","status":200,"time":"2023-09-04T14:05:22+02:00","message":"request"} | |
| 22 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/admin","status":200,"time":"2023-09-04T14:05:23+02:00","message":"request"} | |
| 23 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/admin","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |
| 24 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/js/custom.js","status":404,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |
| 25 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/css/tailwind.css","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |
| 26 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/htmx.min.js","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |
| 27 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/alpine.min.js","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |
| 28 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/iconoir.css","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |
| 29 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/imgs/gordon-mascot-hq-trsp.png","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |
| 30 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |
| 31 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |
| 32 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/favicon.ico","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |
| 33 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/admin","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |
| 34 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/css/tailwind.css","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |
| 35 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/alpine.min.js","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |
| 36 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/iconoir.css","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |
| 37 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/htmx.min.js","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |
| 38 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/js/custom.js","status":404,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |
| 39 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/imgs/gordon-mascot-hq-trsp.png","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |
| 40 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |
| 41 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |
| 42 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/favicon.ico","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |
| 43 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:22+02:00","message":"request"} | |
| 44 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:32:22+02:00","message":"request"} | |
| 45 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:42+02:00","message":"request"} | |
| 46 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:42+02:00","message":"request"} | |
| 47 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:32:42+02:00","message":"request"} | |
| 48 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:46+02:00","message":"request"} | |
| 49 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:47+02:00","message":"request"} | |
| 50 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:32:47+02:00","message":"request"} | |
| 51 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:48+02:00","message":"request"} | |
| 52 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:49+02:00","message":"request"} | |
| 53 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:32:49+02:00","message":"request"} | |
| 54 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:53+02:00","message":"request"} | |
| 55 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:54+02:00","message":"request"} | |
| 56 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:32:54+02:00","message":"request"} | |
| 57 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:55+02:00","message":"request"} | |
| 58 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/admin","status":200,"time":"2023-09-04T14:33:13+02:00","message":"request"} | |
| 59 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/css/tailwind.css","status":200,"time":"2023-09-04T14:33:13+02:00","message":"request"} | |
| 60 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/iconoir.css","status":200,"time":"2023-09-04T14:33:13+02:00","message":"request"} | |
| 61 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/js/custom.js","status":404,"time":"2023-09-04T14:33:13+02:00","message":"request"} | |
| 62 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/alpine.min.js","status":200,"time":"2023-09-04T14:33:14+02:00","message":"request"} | |
| 63 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/htmx.min.js","status":200,"time":"2023-09-04T14:33:14+02:00","message":"request"} | |
| 64 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:33:14+02:00","message":"request"} | |
| 65 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:33:14+02:00","message":"request"} | |
| 66 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/imgs/gordon-mascot-hq-trsp.png","status":200,"time":"2023-09-04T14:33:14+02:00","message":"request"} | |
| 67 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/favicon.ico","status":200,"time":"2023-09-04T14:33:14+02:00","message":"request"} | |
| @@ -18,3 +18,50 @@ | |||||
| 18 | {"level":"info","type":"http","remote_ip":"::1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T11:57:48+02:00","message":"request"} | 18 | {"level":"info","type":"http","remote_ip":"::1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T11:57:48+02:00","message":"request"} | ||
| 19 | {"level":"info","type":"http","remote_ip":"::1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T11:57:48+02:00","message":"request"} | 19 | {"level":"info","type":"http","remote_ip":"::1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T11:57:48+02:00","message":"request"} | ||
| 20 | {"level":"info","type":"http","remote_ip":"::1","method":"GET","URI":"/favicon.ico","status":200,"time":"2023-09-04T11:57:48+02:00","message":"request"} | 20 | {"level":"info","type":"http","remote_ip":"::1","method":"GET","URI":"/favicon.ico","status":200,"time":"2023-09-04T11:57:48+02:00","message":"request"} | ||
| 21 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/admin","status":200,"time":"2023-09-04T14:05:22+02:00","message":"request"} | |||
| 22 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/admin","status":200,"time":"2023-09-04T14:05:23+02:00","message":"request"} | |||
| 23 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/admin","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |||
| 24 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/js/custom.js","status":404,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |||
| 25 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/css/tailwind.css","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |||
| 26 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/htmx.min.js","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |||
| 27 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/alpine.min.js","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |||
| 28 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/iconoir.css","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |||
| 29 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/imgs/gordon-mascot-hq-trsp.png","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |||
| 30 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |||
| 31 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |||
| 32 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/favicon.ico","status":200,"time":"2023-09-04T14:05:25+02:00","message":"request"} | |||
| 33 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/admin","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |||
| 34 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/css/tailwind.css","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |||
| 35 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/alpine.min.js","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |||
| 36 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/iconoir.css","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |||
| 37 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/htmx.min.js","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |||
| 38 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/js/custom.js","status":404,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |||
| 39 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/imgs/gordon-mascot-hq-trsp.png","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |||
| 40 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |||
| 41 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |||
| 42 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/favicon.ico","status":200,"time":"2023-09-04T14:31:47+02:00","message":"request"} | |||
| 43 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:22+02:00","message":"request"} | |||
| 44 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:32:22+02:00","message":"request"} | |||
| 45 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:42+02:00","message":"request"} | |||
| 46 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:42+02:00","message":"request"} | |||
| 47 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:32:42+02:00","message":"request"} | |||
| 48 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:46+02:00","message":"request"} | |||
| 49 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:47+02:00","message":"request"} | |||
| 50 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:32:47+02:00","message":"request"} | |||
| 51 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:48+02:00","message":"request"} | |||
| 52 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:49+02:00","message":"request"} | |||
| 53 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:32:49+02:00","message":"request"} | |||
| 54 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:53+02:00","message":"request"} | |||
| 55 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:54+02:00","message":"request"} | |||
| 56 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:32:54+02:00","message":"request"} | |||
| 57 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:32:55+02:00","message":"request"} | |||
| 58 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/admin","status":200,"time":"2023-09-04T14:33:13+02:00","message":"request"} | |||
| 59 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/css/tailwind.css","status":200,"time":"2023-09-04T14:33:13+02:00","message":"request"} | |||
| 60 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/iconoir.css","status":200,"time":"2023-09-04T14:33:13+02:00","message":"request"} | |||
| 61 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/js/custom.js","status":404,"time":"2023-09-04T14:33:13+02:00","message":"request"} | |||
| 62 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/alpine.min.js","status":200,"time":"2023-09-04T14:33:14+02:00","message":"request"} | |||
| 63 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/libs/htmx.min.js","status":200,"time":"2023-09-04T14:33:14+02:00","message":"request"} | |||
| 64 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/LilitaOne/LilitaOne-Regular.ttf","status":200,"time":"2023-09-04T14:33:14+02:00","message":"request"} | |||
| 65 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2","status":200,"time":"2023-09-04T14:33:14+02:00","message":"request"} | |||
| 66 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/assets/imgs/gordon-mascot-hq-trsp.png","status":200,"time":"2023-09-04T14:33:14+02:00","message":"request"} | |||
| 67 | + | {"level":"info","type":"http","remote_ip":"127.0.0.1","method":"GET","URI":"/favicon.ico","status":200,"time":"2023-09-04T14:33:14+02:00","message":"request"} | |||
A pkg/utils/terminal.go +65 -0
| @@ -0,0 +1,65 @@ | |||
| 1 | + | package utils | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "net/http" | |
| 5 | + | "os" | |
| 6 | + | "os/exec" | |
| 7 | + | "os/signal" | |
| 8 | + | "syscall" | |
| 9 | + | "time" | |
| 10 | + | ||
| 11 | + | "github.com/rs/zerolog" | |
| 12 | + | ) | |
| 13 | + | ||
| 14 | + | // SetRawMode sets the terminal to raw mode. | |
| 15 | + | func SetRawMode() { | |
| 16 | + | cmd := exec.Command("stty", "raw", "-echo") | |
| 17 | + | cmd.Stdin = os.Stdin | |
| 18 | + | _ = cmd.Run() | |
| 19 | + | } | |
| 20 | + | ||
| 21 | + | // RestoreTerminal restores the terminal settings. | |
| 22 | + | func RestoreTerminal() { | |
| 23 | + | cmd := exec.Command("stty", "-raw", "echo") | |
| 24 | + | cmd.Stdin = os.Stdin | |
| 25 | + | _ = cmd.Run() | |
| 26 | + | } | |
| 27 | + | ||
| 28 | + | func RunAppCatchSIGINT(startServerFunc func() error, logger *zerolog.Logger) { | |
| 29 | + | // Start the server in a separate goroutine | |
| 30 | + | go func() { | |
| 31 | + | if err := startServerFunc(); err != nil && err != http.ErrServerClosed { | |
| 32 | + | logger.Fatal().Err(err).Msg("Failed to start the server") | |
| 33 | + | } | |
| 34 | + | }() | |
| 35 | + | ||
| 36 | + | // Catch SIGINT and SIGTERM signals without raw mode initially | |
| 37 | + | c := make(chan os.Signal, 1) | |
| 38 | + | signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) | |
| 39 | + | <-c | |
| 40 | + | ||
| 41 | + | logger.Warn().Msg("Graceful shutdown initiated") | |
| 42 | + | logger.Warn().Msg("Server will shutdown in 5 seconds press ENTER to cancel") | |
| 43 | + | ||
| 44 | + | // Now, set raw mode | |
| 45 | + | SetRawMode() | |
| 46 | + | defer RestoreTerminal() | |
| 47 | + | ||
| 48 | + | // Channel to signal a key press | |
| 49 | + | keypress := make(chan struct{}) | |
| 50 | + | ||
| 51 | + | // Goroutine to listen for a key press | |
| 52 | + | go func() { | |
| 53 | + | var b []byte = make([]byte, 1) | |
| 54 | + | os.Stdin.Read(b) | |
| 55 | + | keypress <- struct{}{} | |
| 56 | + | }() | |
| 57 | + | ||
| 58 | + | // Wait for either a key press or the 5-second timer | |
| 59 | + | select { | |
| 60 | + | case <-time.After(5 * time.Second): | |
| 61 | + | logger.Info().Msg("Server shutdown") | |
| 62 | + | case <-keypress: | |
| 63 | + | logger.Info().Msg("Shutdown cancelled by user") | |
| 64 | + | } | |
| 65 | + | } | |
| @@ -0,0 +1,65 @@ | |||||
| 1 | + | package utils | |||
| 2 | + | ||||
| 3 | + | import ( | |||
| 4 | + | "net/http" | |||
| 5 | + | "os" | |||
| 6 | + | "os/exec" | |||
| 7 | + | "os/signal" | |||
| 8 | + | "syscall" | |||
| 9 | + | "time" | |||
| 10 | + | ||||
| 11 | + | "github.com/rs/zerolog" | |||
| 12 | + | ) | |||
| 13 | + | ||||
| 14 | + | // SetRawMode sets the terminal to raw mode. | |||
| 15 | + | func SetRawMode() { | |||
| 16 | + | cmd := exec.Command("stty", "raw", "-echo") | |||
| 17 | + | cmd.Stdin = os.Stdin | |||
| 18 | + | _ = cmd.Run() | |||
| 19 | + | } | |||
| 20 | + | ||||
| 21 | + | // RestoreTerminal restores the terminal settings. | |||
| 22 | + | func RestoreTerminal() { | |||
| 23 | + | cmd := exec.Command("stty", "-raw", "echo") | |||
| 24 | + | cmd.Stdin = os.Stdin | |||
| 25 | + | _ = cmd.Run() | |||
| 26 | + | } | |||
| 27 | + | ||||
| 28 | + | func RunAppCatchSIGINT(startServerFunc func() error, logger *zerolog.Logger) { | |||
| 29 | + | // Start the server in a separate goroutine | |||
| 30 | + | go func() { | |||
| 31 | + | if err := startServerFunc(); err != nil && err != http.ErrServerClosed { | |||
| 32 | + | logger.Fatal().Err(err).Msg("Failed to start the server") | |||
| 33 | + | } | |||
| 34 | + | }() | |||
| 35 | + | ||||
| 36 | + | // Catch SIGINT and SIGTERM signals without raw mode initially | |||
| 37 | + | c := make(chan os.Signal, 1) | |||
| 38 | + | signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) | |||
| 39 | + | <-c | |||
| 40 | + | ||||
| 41 | + | logger.Warn().Msg("Graceful shutdown initiated") | |||
| 42 | + | logger.Warn().Msg("Server will shutdown in 5 seconds press ENTER to cancel") | |||
| 43 | + | ||||
| 44 | + | // Now, set raw mode | |||
| 45 | + | SetRawMode() | |||
| 46 | + | defer RestoreTerminal() | |||
| 47 | + | ||||
| 48 | + | // Channel to signal a key press | |||
| 49 | + | keypress := make(chan struct{}) | |||
| 50 | + | ||||
| 51 | + | // Goroutine to listen for a key press | |||
| 52 | + | go func() { | |||
| 53 | + | var b []byte = make([]byte, 1) | |||
| 54 | + | os.Stdin.Read(b) | |||
| 55 | + | keypress <- struct{}{} | |||
| 56 | + | }() | |||
| 57 | + | ||||
| 58 | + | // Wait for either a key press or the 5-second timer | |||
| 59 | + | select { | |||
| 60 | + | case <-time.After(5 * time.Second): | |||
| 61 | + | logger.Info().Msg("Server shutdown") | |||
| 62 | + | case <-keypress: | |||
| 63 | + | logger.Info().Msg("Shutdown cancelled by user") | |||
| 64 | + | } | |||
| 65 | + | } | |||