fix(proxy): fail fast on HTTP bind errors
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
6f0f695054
commit
0bb5ce827b
2 changed files with 69 additions and 3 deletions
|
|
@ -1,7 +1,9 @@
|
|||
package proxy
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
@ -69,3 +71,53 @@ func TestProxy_allowHTTP_Ugly(t *testing.T) {
|
|||
t.Fatalf("expected status %d, got %d", http.StatusUnauthorized, status)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxy_startHTTP_Good(t *testing.T) {
|
||||
p := &Proxy{
|
||||
config: &Config{
|
||||
HTTP: HTTPConfig{
|
||||
Enabled: true,
|
||||
Host: "127.0.0.1",
|
||||
Port: 0,
|
||||
},
|
||||
},
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
|
||||
if ok := p.startHTTP(); !ok {
|
||||
t.Fatal("expected HTTP server to start on a free port")
|
||||
}
|
||||
p.Stop()
|
||||
}
|
||||
|
||||
func TestProxy_startHTTP_Bad(t *testing.T) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("listen on ephemeral port: %v", err)
|
||||
}
|
||||
defer listener.Close()
|
||||
|
||||
host, port, err := net.SplitHostPort(listener.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatalf("split listener addr: %v", err)
|
||||
}
|
||||
portNum, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
t.Fatalf("parse listener port: %v", err)
|
||||
}
|
||||
|
||||
p := &Proxy{
|
||||
config: &Config{
|
||||
HTTP: HTTPConfig{
|
||||
Enabled: true,
|
||||
Host: host,
|
||||
Port: uint16(portNum),
|
||||
},
|
||||
},
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
|
||||
if ok := p.startHTTP(); ok {
|
||||
t.Fatal("expected HTTP server start to fail when the port is already in use")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,7 +220,10 @@ func (p *Proxy) Start() {
|
|||
p.watcher.Start()
|
||||
}
|
||||
if p.config.HTTP.Enabled {
|
||||
p.startHTTP()
|
||||
if !p.startHTTP() {
|
||||
p.Stop()
|
||||
return
|
||||
}
|
||||
}
|
||||
p.ticker = time.NewTicker(time.Second)
|
||||
go func() {
|
||||
|
|
@ -585,7 +588,10 @@ func parseTLSVersion(value string) uint16 {
|
|||
}
|
||||
}
|
||||
|
||||
func (p *Proxy) startHTTP() {
|
||||
func (p *Proxy) startHTTP() bool {
|
||||
if p == nil || !p.config.HTTP.Enabled {
|
||||
return true
|
||||
}
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/1/summary", func(w http.ResponseWriter, r *http.Request) {
|
||||
if status, ok := p.allowHTTP(r); !ok {
|
||||
|
|
@ -618,10 +624,18 @@ func (p *Proxy) startHTTP() {
|
|||
p.writeJSON(w, p.minersDocument())
|
||||
})
|
||||
addr := net.JoinHostPort(p.config.HTTP.Host, strconv.Itoa(int(p.config.HTTP.Port)))
|
||||
listener, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
p.httpServer = &http.Server{Addr: addr, Handler: mux}
|
||||
go func() {
|
||||
_ = p.httpServer.ListenAndServe()
|
||||
err := p.httpServer.Serve(listener)
|
||||
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
p.Stop()
|
||||
}
|
||||
}()
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *Proxy) allowHTTP(r *http.Request) (int, bool) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue