package server import ( "context" "errors" "fmt" "net/http" "time" "github.com/dhao2001/mygo/internal/config" ) // Address returns the HTTP listen address for a server config. func Address(cfg config.ServerConfig) string { return fmt.Sprintf("%s:%d", cfg.Host, cfg.Port) } // RunWithGracefulShutdown starts an HTTP server and shuts it down when ctx is canceled. func RunWithGracefulShutdown(ctx context.Context, addr string, handler http.Handler) error { if handler == nil { return errors.New("handler: must not be nil") } httpServer := &http.Server{ Addr: addr, Handler: handler, ReadHeaderTimeout: 5 * time.Second, } errCh := make(chan error, 1) go func() { errCh <- httpServer.ListenAndServe() }() select { case <-ctx.Done(): shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := httpServer.Shutdown(shutdownCtx); err != nil { return fmt.Errorf("shutdown server: %w", err) } return nil case err := <-errCh: if errors.Is(err, http.ErrServerClosed) { return nil } return fmt.Errorf("listen and serve: %w", err) } }