/
local_server.go
115 lines (94 loc) · 2.67 KB
/
local_server.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
package localserver
import (
"log"
"net"
"net/http"
"time"
"crypto/tls"
"github.com/etix/stoppableListener"
)
const (
defaultCaKey = "server_ca.key"
defaultCaPem = "server_ca.pem"
)
// LocalServer provides a simple, local HTTP server.
type LocalServer struct {
hostPort string
scheme string
listener *stoppableListener.StoppableListener
tlsConfigProvider *tlsConfigProvider
}
// NewLocalServer creates new instance of a HTTP server. It requires host, port and protocol scheme.
func NewLocalServer(hostPort string, scheme string) *LocalServer {
tlsConfigProvider := newTLSConfigProvider()
return &LocalServer{hostPort: hostPort, scheme: scheme, tlsConfigProvider: tlsConfigProvider}
}
// Start runs the server basing on chosen protocol scheme.
func (l *LocalServer) Start() {
if l.scheme == "http" {
l.StartHTTP()
} else if l.scheme == "https" {
l.StartTLS(defaultCaKey, defaultCaPem)
} else {
log.Fatalf("Unknown scheme specified: %v\n", l.scheme)
}
}
// StartHTTP runs the HTTP server.
func (l *LocalServer) StartHTTP() {
listener, error := net.Listen("tcp", l.hostPort)
if nil != error {
log.Fatalln(error)
}
l.listener = stoppableListener.Handle(listener)
l.startServing()
}
// StartTLS runs the TLS server.
func (l *LocalServer) StartTLS(caPemPath, caKeyPath string) {
config := l.tlsConfigProvider.Provide(caPemPath, caKeyPath)
listener, error := tls.Listen("tcp", l.hostPort, config)
if nil != error {
log.Fatalln(error)
}
l.listener = stoppableListener.Handle(listener)
l.startServing()
}
func (l *LocalServer) startServing() {
go http.Serve(l.listener, nil)
l.waitUntilReady()
}
// Stop method stops the running server.
func (l *LocalServer) Stop() {
l.listener.Stop <- true
l.waitUntilStopped()
}
func (l *LocalServer) waitUntilReady() {
var ready bool
client := l.createHTTPClient()
for !ready {
if _, error := client.Get(l.scheme + "://" + l.hostPort); nil != error {
log.Printf("Waiting for local server to start: %v, error: %v\n", l.hostPort, error)
time.Sleep(10 * time.Millisecond)
} else {
ready = true
}
}
log.Printf("Local server started: %v\n", l.hostPort)
}
func (l *LocalServer) waitUntilStopped() {
var stopped bool
client := l.createHTTPClient()
for !stopped {
if _, error := client.Get(l.scheme + "://" + l.hostPort); nil == error {
log.Printf("Waiting for local server to stop: %v\n", l.hostPort)
time.Sleep(10 * time.Millisecond)
} else {
stopped = true
}
}
log.Printf("Local server stopped: %v\n", l.hostPort)
}
func (l *LocalServer) createHTTPClient() *http.Client {
tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
client := &http.Client{Transport: tr}
return client
}