4
0

server.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package webapi
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "log/slog"
  7. "net/http"
  8. "golang.org/x/sync/errgroup"
  9. )
  10. func NewServer(listeners []string, logger *slog.Logger, handler Handler) *Server {
  11. servers := make([]*http.Server, 0, len(listeners))
  12. for _, l := range listeners {
  13. mux := http.NewServeMux()
  14. mux.HandleFunc("GET /", handler.GetHelloWorldHandler)
  15. servers = append(servers, &http.Server{
  16. Addr: l,
  17. Handler: mux,
  18. })
  19. }
  20. return &Server{
  21. servers: servers,
  22. logger: logger,
  23. }
  24. }
  25. // Server hosts an HTTP endpoint capable of handling AIM-style Kerberos
  26. // authentication. The messages are structured as SNACs transmitted over HTTP.
  27. type Server struct {
  28. servers []*http.Server
  29. logger *slog.Logger
  30. }
  31. func (s *Server) ListenAndServe() error {
  32. if len(s.servers) == 0 {
  33. s.logger.Debug("no webapi listeners defined")
  34. return nil
  35. }
  36. ctx, cancel := context.WithCancel(context.Background())
  37. defer cancel()
  38. g, ctx := errgroup.WithContext(ctx)
  39. for _, server := range s.servers {
  40. g.Go(func() error {
  41. s.logger.Info("starting server", "addr", server.Addr)
  42. if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
  43. cancel()
  44. return fmt.Errorf("unable to start webapi server: %w", err)
  45. }
  46. return nil
  47. })
  48. }
  49. return g.Wait()
  50. }
  51. func (s *Server) Shutdown(ctx context.Context) error {
  52. if len(s.servers) > 0 {
  53. for _, srv := range s.servers {
  54. _ = srv.Shutdown(ctx)
  55. }
  56. s.logger.Info("shutdown complete")
  57. }
  58. return nil
  59. }