package main import ( "context" "errors" "fmt" "log/slog" "net/http" "os" "os/signal" "syscall" "time" ) const ( defaultIdleTimeout = time.Minute defaultReadTimeout = 5 * time.Second defaultWriteTimeout = 10 * time.Second defaultShutdownPeriod = 30 * time.Second ) func (app *application) serveHTTP() error { srv := &http.Server{ Addr: fmt.Sprintf(":%d", app.config.httpPort), Handler: app.routes(), ErrorLog: slog.NewLogLogger(app.logger.Handler(), slog.LevelWarn), IdleTimeout: defaultIdleTimeout, ReadTimeout: defaultReadTimeout, WriteTimeout: defaultWriteTimeout, } shutdownErrorChan := make(chan error) go func() { quitChan := make(chan os.Signal, 1) signal.Notify(quitChan, syscall.SIGINT, syscall.SIGTERM) <-quitChan ctx, cancel := context.WithTimeout(context.Background(), defaultShutdownPeriod) defer cancel() shutdownErrorChan <- srv.Shutdown(ctx) }() app.logger.Info("starting server", slog.Group("server", "addr", srv.Addr)) err := srv.ListenAndServe() if !errors.Is(err, http.ErrServerClosed) { return err } err = <-shutdownErrorChan if err != nil { return err } app.logger.Info("stopped server", slog.Group("server", "addr", srv.Addr)) app.wg.Wait() return nil }