cerrado @ 7ff4cac4fc23060a56b9c33a3453c2d26629b699

 1package worker
 2
 3import (
 4	"context"
 5	"errors"
 6	"net"
 7	"net/http"
 8	"net/url"
 9)
10
11var (
12	UnsupportedSchemeErr = errors.New("Ivalid schema, only tcp and unix supported")
13)
14
15type ServerTask struct {
16	addr    string
17	handler http.Handler
18}
19
20func NewServerTask(addr string, handler http.Handler) *ServerTask {
21	return &ServerTask{
22		addr:    addr,
23		handler: handler,
24	}
25}
26
27func (s *ServerTask) Start(ctx context.Context) error {
28	done := make(chan error)
29
30	listen, err := getListen(s.addr)
31	if err != nil {
32		return err
33	}
34	server := &http.Server{
35		Handler: s.handler,
36	}
37
38	go func() {
39		done <- server.Serve(listen)
40	}()
41
42	select {
43	// if ListenAndServe error for something other than context.Canceled
44	//(e.g.: address already in use) it trigger done to return sonner with
45	// the return error
46	case err := <-done:
47		return err
48
49	// in case of context canceled it will manually trigger the server to
50	// shutdown, and return its error, which is most cases, but not limited, is
51	// context.Canceled.
52	case <-ctx.Done():
53		return server.Shutdown(ctx)
54	}
55}
56
57func getListen(addr string) (net.Listener, error) {
58	u, err := url.Parse(addr)
59	if err != nil {
60		return nil, err
61	}
62
63	switch u.Scheme {
64	case "tcp":
65		return net.Listen(u.Scheme, u.Host)
66	case "unix":
67		host, err := url.JoinPath("/", u.Host, u.Path)
68		if err != nil {
69			return nil, err
70		}
71		return net.Listen(u.Scheme, host)
72	default:
73		return nil, UnsupportedSchemeErr
74	}
75}