Skip to content

Instantly share code, notes, and snippets.

@adomaskizogian
Created March 19, 2024 12:24
Show Gist options
  • Select an option

  • Save adomaskizogian/a2df1149d750fef843718e1b04e93689 to your computer and use it in GitHub Desktop.

Select an option

Save adomaskizogian/a2df1149d750fef843718e1b04e93689 to your computer and use it in GitHub Desktop.
go http quick setup
package main
import (
"context"
"errors"
"fmt"
"log/slog"
"net/http"
"net/http/httputil"
"os"
"os/signal"
"runtime"
"syscall"
"time"
)
func main() {
var retCode int
defer func() {
os.Exit(retCode)
}()
defer func() {
if err := recover(); err != nil {
buf := make([]byte, 64<<10)
buf = buf[:runtime.Stack(buf, false)]
slog.Error("recovered panic on main", "panic", err, "stack", string(buf))
retCode = 2
}
}()
logHandler := slog.NewTextHandler(os.Stdout, nil)
slog.SetDefault(slog.New(logHandler))
if err := run(context.Background()); err != nil {
slog.Error("service stopped abnormally", "error", err)
retCode = 1
}
}
func run(ctx context.Context) error {
srv := &http.Server{
Addr: ":8080",
Handler: dumper(),
ErrorLog: slog.NewLogLogger(slog.Default().Handler(), slog.LevelError),
}
ctx, cancel := signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
go func() {
defer func() {
if err := recover(); err != nil {
buf := make([]byte, 64<<10)
buf = buf[:runtime.Stack(buf, false)]
slog.Error("recovered panic on ListenAndServe goroutine", "panic", err, "stack", string(buf))
cancel()
}
}()
slog.Info("server is listening for incoming requests", "addr", srv.Addr)
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
slog.Error("ListenAndServe stopped unexpectedly", "error", err)
cancel()
}
}()
<-ctx.Done()
timeoutCtx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
slog.Info("stopping gracefully. force shutdown in 5 seconds")
if err := srv.Shutdown(timeoutCtx); err != nil {
slog.Warn("server shutdown returned error", "error", err)
}
slog.Info("bye")
return nil
}
func dumper() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
dump, err := httputil.DumpRequest(r, true)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
fmt.Println(string(dump))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment