package http import ( "context" "log" "net" "net/http" "net/netip" "os" "strings" "time" ) type HttpServer struct { s http.Server addr net.Addr } func NewHttpServer(r http.Handler) *HttpServer { return &HttpServer{s: http.Server{ ReadTimeout: 3 * time.Second, WriteTimeout: 3 * time.Second, Handler: r}} } func (s *HttpServer) Start(address string) error { var network string if !strings.ContainsRune(address, ':') { network = "unix" } else { ap, err := netip.ParseAddrPort(address) if err != nil { return err } if ap.Addr().Is4() { network = "tcp4" } else if ap.Addr().Is6() { network = "tcp6" } } listener, err := net.Listen(network, address) if err != nil { return err } if listener.Addr().Network() == "unix" { os.Chmod(address, 0777) } s.addr = listener.Addr() go func() { if err = s.s.Serve(listener); err != nil && err != http.ErrServerClosed { log.Fatalln(err) } }() return nil } func (s *HttpServer) Stop() error { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if s.addr.Network() == "unix" { defer os.Remove(s.addr.String()) } if err := s.s.Shutdown(ctx); err != nil { return err } return nil }