From 06a28a461d1851a65821a94d29ab97d2167a28ba Mon Sep 17 00:00:00 2001 From: Eugene Bujak Date: Wed, 6 Feb 2019 16:47:17 +0300 Subject: [PATCH] /install/configure -- Rebind HTTP server when we get new host and port --- app.go | 21 +++++++++++++++++---- control.go | 6 ++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/app.go b/app.go index 71f3ee82..f72a9d08 100644 --- a/app.go +++ b/app.go @@ -20,6 +20,7 @@ import ( // VersionString will be set through ldflags, contains current version var VersionString = "undefined" +var httpServer *http.Server const ( // Used in config to indicate that syslog or eventlog (win) should be used for logger output @@ -147,10 +148,22 @@ func run(args options) { http.Handle("/install.html", preInstallHandler(http.FileServer(box))) registerControlHandlers() - address := net.JoinHostPort(config.BindHost, strconv.Itoa(config.BindPort)) - URL := fmt.Sprintf("http://%s", address) - log.Println("Go to " + URL) - log.Fatal(http.ListenAndServe(address, nil)) + // this loop is used as an ability to change listening host and/or port + for { + address := net.JoinHostPort(config.BindHost, strconv.Itoa(config.BindPort)) + URL := fmt.Sprintf("http://%s", address) + log.Println("Go to " + URL) + // we need to have new instance, because after Shutdown() the Server is not usable + httpServer = &http.Server{ + Addr: address, + } + err := httpServer.ListenAndServe() + if err != http.ErrServerClosed { + log.Fatal(err) + os.Exit(1) + } + // We use ErrServerClosed as a sign that we need to rebind on new address, so go back to the start of the loop + } } // initWorkingDir initializes the ourBinaryDir (basically, we use it as a working dir) diff --git a/control.go b/control.go index 3e322540..912f3425 100644 --- a/control.go +++ b/control.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "fmt" "io/ioutil" @@ -793,6 +794,11 @@ func handleInstallConfigure(w http.ResponseWriter, r *http.Request) { } httpUpdateConfigReloadDNSReturnOK(w, r) + // this needs to be done in a goroutine because Shutdown() is a blocking call, and it will block + // until all requests are finished, and _we_ are inside a request right now, so it will block indefinitely + go func() { + httpServer.Shutdown(context.TODO()) + }() } func registerControlHandlers() {