forked from stellar/go
-
Notifications
You must be signed in to change notification settings - Fork 6
/
main.go
117 lines (99 loc) · 3.27 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Package http provides easy access to Stellar's best practices for building
// http servers. The primary method to use is `Serve`, which sets up
// an server that can support http/2 and can gracefully quit after receiving a
// SIGINT signal.
//
package http
import (
stdhttp "net/http"
"net/url"
"os"
"time"
"github.com/stellar/go/support/config"
"github.com/stellar/go/support/errors"
"github.com/stellar/go/support/log"
"golang.org/x/net/http2"
"gopkg.in/tylerb/graceful.v1"
)
// DefaultListenAddr represents the default address and port on which a server
// will listen, provided it is not overridden by setting the `ListenAddr` field
// on a `Config` struct.
const DefaultListenAddr = "0.0.0.0:8080"
// DefaultShutdownGracePeriod represents the default time in which the running
// process will allow outstanding http requests to complete before aborting
// them. It will be used when a grace period of 0 is used, which normally
// signifies "no timeout" to our graceful shutdown package. We choose not to
// provide a "no timeout" mode at present. Feel free to set the value to a year
// or something if you need a timeout that is effectively "no timeout"; We
// believe that most servers should use a sane timeout and prefer one for the
// default configuration.
const DefaultShutdownGracePeriod = 10 * time.Second
// SimpleHTTPClientInterface helps mocking http.Client in tests
type SimpleHTTPClientInterface interface {
PostForm(url string, data url.Values) (*stdhttp.Response, error)
Get(url string) (*stdhttp.Response, error)
}
// Config represents the configuration of an http server that can be provided to
// `Run`.
type Config struct {
Handler stdhttp.Handler
ListenAddr string
TLS *config.TLS
ShutdownGracePeriod time.Duration
OnStarting func()
OnStopping func()
OnStopped func()
}
// Run starts an http server using the provided config struct.
//
// This method configures the process to listen for termination signals (SIGINT
// and SIGTERM) to trigger a graceful shutdown by way of the graceful package
// (https://github.com/tylerb/graceful).
func Run(conf Config) {
srv := setup(conf)
http2.ConfigureServer(srv.Server, nil)
if conf.OnStarting != nil {
conf.OnStarting()
}
var err error
if conf.TLS != nil {
err = srv.ListenAndServeTLS(conf.TLS.CertificateFile, conf.TLS.PrivateKeyFile)
} else {
err = srv.ListenAndServe()
}
if err != nil {
log.Error(errors.Wrap(err, "failed to start server"))
os.Exit(1)
}
if conf.OnStopped != nil {
conf.OnStopped()
}
os.Exit(0)
}
// setup is a utility function to configure a new graceful server. Its main
// purpose is to allow us to test the setup process without having to resort to
// a call the `Run`, which takes over the process.
func setup(conf Config) *graceful.Server {
if conf.Handler == nil {
panic("Handler must not be nil")
}
if conf.ListenAddr == "" {
conf.ListenAddr = DefaultListenAddr
}
timeout := DefaultShutdownGracePeriod
if conf.ShutdownGracePeriod != 0 {
timeout = conf.ShutdownGracePeriod
}
return &graceful.Server{
Timeout: timeout,
Server: &stdhttp.Server{
Addr: conf.ListenAddr,
Handler: conf.Handler,
},
ShutdownInitiated: func() {
if conf.OnStopping != nil {
conf.OnStopping()
}
},
}
}