4
4
"context"
5
5
"fmt"
6
6
"net/http"
7
+ "net/http/httptest"
7
8
"time"
8
9
9
10
"github.com/netlify/netlify-commons/nconf"
@@ -17,6 +18,7 @@ import (
17
18
type Server struct {
18
19
log logrus.FieldLogger
19
20
svr * http.Server
21
+ api APIDefinition
20
22
}
21
23
22
24
type Config struct {
@@ -25,9 +27,10 @@ type Config struct {
25
27
TLS nconf.TLSConfig
26
28
}
27
29
28
- // APIDefinition is used to define the routes used by the API
30
+ // APIDefinition is used to control lifecycle of the API
29
31
type APIDefinition interface {
30
- AddRoutes (r router.Router )
32
+ Start (r router.Router ) error
33
+ Stop ()
31
34
}
32
35
33
36
func New (log logrus.FieldLogger , projectName string , config Config , api APIDefinition ) (* Server , error ) {
@@ -37,14 +40,17 @@ func New(log logrus.FieldLogger, projectName string, config Config, api APIDefin
37
40
router .OptTracingMiddleware (log , projectName ),
38
41
)
39
42
40
- api .AddRoutes (r )
43
+ if err := api .Start (r ); err != nil {
44
+ return nil , errors .Wrap (err , "Failed to start API" )
45
+ }
41
46
42
47
s := Server {
43
48
log : log .WithField ("component" , "server" ),
44
49
svr : & http.Server {
45
50
Addr : fmt .Sprintf (":%d" , config .Port ),
46
51
Handler : r ,
47
52
},
53
+ api : api ,
48
54
}
49
55
50
56
if config .TLS .Enabled {
@@ -77,20 +83,40 @@ func (s *Server) ListenAndServe() error {
77
83
} else {
78
84
err = s .svr .ListenAndServe ()
79
85
}
86
+
87
+ // Now that server is no longer listening, shutdown the API
88
+ s .log .Info ("Listener shutdown, stopping API" )
89
+
90
+ s .api .Stop ()
91
+
92
+ s .log .Debug ("Completed shutting down the underlying API" )
93
+
80
94
if err == http .ErrServerClosed {
81
95
return nil
82
96
}
83
97
return err
84
98
}
85
99
100
+ func (s * Server ) TestServer () * httptest.Server {
101
+ return httptest .NewServer (s .svr .Handler )
102
+ }
103
+
86
104
type apiFunc struct {
87
- f func (router.Router )
105
+ start func (router.Router ) error
106
+ stop func ()
88
107
}
89
108
90
- func (a apiFunc ) AddRoutes (r router.Router ) {
91
- a . f (r )
109
+ func (a apiFunc ) Start (r router.Router ) error {
110
+ return a . start (r )
92
111
}
93
112
94
- func APIFunc (f func (router.Router )) APIDefinition {
95
- return apiFunc {f }
113
+ func (a apiFunc ) Stop () {
114
+ a .stop ()
115
+ }
116
+
117
+ func APIFunc (start func (router.Router ) error , stop func ()) APIDefinition {
118
+ return apiFunc {
119
+ start : start ,
120
+ stop : stop ,
121
+ }
96
122
}
0 commit comments