Browse Source

Enabled embedded webui

Toby Chui 8 months ago
parent
commit
d16c6b7fac
10 changed files with 78 additions and 41 deletions
  1. 1 1
      main.go
  2. 15 0
      mod/info/logger/logger.go
  3. 0 1
      mod/netstat/netstat.go
  4. 19 7
      mod/uptime/uptime.go
  5. 12 7
      mod/webserv/webserv.go
  6. 7 19
      reverseproxy.go
  7. 1 0
      start.go
  8. 9 0
      upstreams.go
  9. 1 1
      web/snippet/upstreams.html
  10. 13 5
      wrappers.go

+ 1 - 1
main.go

@@ -59,7 +59,7 @@ var (
 	name        = "Zoraxy"
 	version     = "3.0.8"
 	nodeUUID    = "generic" //System uuid, in uuidv4 format
-	development = true      //Set this to false to use embedded web fs
+	development = false     //Set this to false to use embedded web fs
 	bootTime    = time.Now().Unix()
 
 	/*

+ 15 - 0
mod/info/logger/logger.go

@@ -25,6 +25,7 @@ type Logger struct {
 	file           *os.File
 }
 
+// Create a new logger that log to files
 func NewLogger(logFilePrefix string, logFolder string) (*Logger, error) {
 	err := os.MkdirAll(logFolder, 0775)
 	if err != nil {
@@ -53,6 +54,17 @@ func NewLogger(logFilePrefix string, logFolder string) (*Logger, error) {
 	return &thisLogger, nil
 }
 
+// Create a fmt logger that only log to STDOUT
+func NewFmtLogger() (*Logger, error) {
+	return &Logger{
+		Prefix:         "",
+		LogFolder:      "",
+		CurrentLogFile: "",
+		logger:         nil,
+		file:           nil,
+	}, nil
+}
+
 func (l *Logger) getLogFilepath() string {
 	year, month, _ := time.Now().Date()
 	return filepath.Join(l.LogFolder, l.Prefix+"_"+strconv.Itoa(year)+"-"+strconv.Itoa(int(month))+".log")
@@ -97,6 +109,9 @@ func (l *Logger) Log(title string, errorMessage string, originalError error, cop
 
 // Validate if the logging target is still valid (detect any months change)
 func (l *Logger) ValidateAndUpdateLogFilepath() {
+	if l.file == nil {
+		return
+	}
 	expectedCurrentLogFilepath := l.getLogFilepath()
 	if l.CurrentLogFile != expectedCurrentLogFilepath {
 		//Change of month. Update to a new log file

+ 0 - 1
mod/netstat/netstat.go

@@ -39,7 +39,6 @@ type NetStatBuffers struct {
 
 // Get a new network statistic buffers
 func NewNetStatBuffer(recordCount int) (*NetStatBuffers, error) {
-
 	//Flood fill the stats with 0
 	initialStats := []*FlowStat{}
 	for i := 0; i < recordCount; i++ {

+ 19 - 7
mod/uptime/uptime.go

@@ -2,16 +2,23 @@ package uptime
 
 import (
 	"encoding/json"
+	"errors"
 	"log"
 	"net/http"
 	"net/http/cookiejar"
+	"strconv"
 	"strings"
 	"time"
 
 	"golang.org/x/net/publicsuffix"
+	"imuslab.com/zoraxy/mod/info/logger"
 	"imuslab.com/zoraxy/mod/utils"
 )
 
+const (
+	logModuleName = "uptime-monitor"
+)
+
 type Record struct {
 	Timestamp  int64
 	ID         string
@@ -42,6 +49,7 @@ type Config struct {
 	Targets         []*Target
 	Interval        int
 	MaxRecordsStore int
+	Logger          *logger.Logger
 }
 
 type Monitor struct {
@@ -64,6 +72,12 @@ func NewUptimeMonitor(config *Config) (*Monitor, error) {
 		Config:          config,
 		OnlineStatusLog: map[string][]*Record{},
 	}
+
+	if config.Logger == nil {
+		//Use default fmt to log if logger is not provided
+		config.Logger, _ = logger.NewFmtLogger()
+	}
+
 	//Start the endpoint listener
 	ticker := time.NewTicker(time.Duration(config.Interval) * time.Second)
 	done := make(chan bool)
@@ -77,7 +91,7 @@ func NewUptimeMonitor(config *Config) (*Monitor, error) {
 			case <-done:
 				return
 			case t := <-ticker.C:
-				log.Println("Uptime updated - ", t.Unix())
+				thisMonitor.Config.Logger.PrintAndLog(logModuleName, "Uptime updated - "+strconv.Itoa(int(t.Unix())), nil)
 				thisMonitor.ExecuteUptimeCheck()
 			}
 		}
@@ -91,7 +105,7 @@ func (m *Monitor) ExecuteUptimeCheck() {
 		//For each target to check online, do the following
 		var thisRecord Record
 		if target.Protocol == "http" || target.Protocol == "https" {
-			online, laterncy, statusCode := getWebsiteStatusWithLatency(target.URL)
+			online, laterncy, statusCode := m.getWebsiteStatusWithLatency(target.URL)
 			thisRecord = Record{
 				Timestamp:  time.Now().Unix(),
 				ID:         target.ID,
@@ -104,7 +118,7 @@ func (m *Monitor) ExecuteUptimeCheck() {
 			}
 
 		} else {
-			log.Println("Unknown protocol: " + target.Protocol + ". Skipping")
+			m.Config.Logger.PrintAndLog(logModuleName, "Unknown protocol: "+target.Protocol, errors.New("unsupported protocol"))
 			continue
 		}
 
@@ -124,8 +138,6 @@ func (m *Monitor) ExecuteUptimeCheck() {
 			m.OnlineStatusLog[target.ID] = thisRecords
 		}
 	}
-
-	//TODO: Write results to db
 }
 
 func (m *Monitor) AddTargetToMonitor(target *Target) {
@@ -201,12 +213,12 @@ func (m *Monitor) HandleUptimeLogRead(w http.ResponseWriter, r *http.Request) {
 */
 
 // Get website stauts with latency given URL, return is conn succ and its latency and status code
-func getWebsiteStatusWithLatency(url string) (bool, int64, int) {
+func (m *Monitor) getWebsiteStatusWithLatency(url string) (bool, int64, int) {
 	start := time.Now().UnixNano() / int64(time.Millisecond)
 	statusCode, err := getWebsiteStatus(url)
 	end := time.Now().UnixNano() / int64(time.Millisecond)
 	if err != nil {
-		log.Println(err.Error())
+		m.Config.Logger.PrintAndLog(logModuleName, "Ping upstream timeout. Assume offline", err)
 		return false, 0, 0
 	} else {
 		diff := end - start

+ 12 - 7
mod/webserv/webserv.go

@@ -5,13 +5,13 @@ import (
 	_ "embed"
 	"errors"
 	"fmt"
-	"log"
 	"net/http"
 	"os"
 	"path/filepath"
 	"sync"
 
 	"imuslab.com/zoraxy/mod/database"
+	"imuslab.com/zoraxy/mod/info/logger"
 	"imuslab.com/zoraxy/mod/utils"
 	"imuslab.com/zoraxy/mod/webserv/filemanager"
 )
@@ -30,6 +30,7 @@ type WebServerOptions struct {
 	EnableDirectoryListing bool               //Enable listing of directory
 	WebRoot                string             //Folder for stroing the static web folders
 	EnableWebDirManager    bool               //Enable web file manager to handle files in web directory
+	Logger                 *logger.Logger     //System logger
 	Sysdb                  *database.Database //Database for storing configs
 }
 
@@ -45,13 +46,16 @@ type WebServer struct {
 
 // NewWebServer creates a new WebServer instance. One instance only
 func NewWebServer(options *WebServerOptions) *WebServer {
+	if options.Logger == nil {
+		options.Logger, _ = logger.NewFmtLogger()
+	}
 	if !utils.FileExists(options.WebRoot) {
 		//Web root folder not exists. Create one with default templates
 		os.MkdirAll(filepath.Join(options.WebRoot, "html"), 0775)
 		os.MkdirAll(filepath.Join(options.WebRoot, "templates"), 0775)
 		indexTemplate, err := templates.ReadFile("templates/index.html")
 		if err != nil {
-			log.Println("Failed to read static wev server template file: ", err.Error())
+			options.Logger.PrintAndLog("static-webserv", "Failed to read static wev server template file: ", err)
 		} else {
 			os.WriteFile(filepath.Join(options.WebRoot, "html", "index.html"), indexTemplate, 0775)
 		}
@@ -102,7 +106,7 @@ func (ws *WebServer) RestorePreviousState() {
 // ChangePort changes the server's port.
 func (ws *WebServer) ChangePort(port string) error {
 	if IsPortInUse(port) {
-		return errors.New("Selected port is used by another process")
+		return errors.New("selected port is used by another process")
 	}
 
 	if ws.isRunning {
@@ -119,6 +123,7 @@ func (ws *WebServer) ChangePort(port string) error {
 		return err
 	}
 
+	ws.option.Logger.PrintAndLog("static-webserv", "Listening port updated to "+port, nil)
 	ws.option.Sysdb.Write("webserv", "port", port)
 
 	return nil
@@ -141,7 +146,7 @@ func (ws *WebServer) Start() error {
 
 	//Check if the port is usable
 	if IsPortInUse(ws.option.Port) {
-		return errors.New("Port already in use or access denied by host OS")
+		return errors.New("port already in use or access denied by host OS")
 	}
 
 	//Dispose the old mux and create a new one
@@ -159,12 +164,12 @@ func (ws *WebServer) Start() error {
 	go func() {
 		if err := ws.server.ListenAndServe(); err != nil {
 			if err != http.ErrServerClosed {
-				fmt.Printf("Web server error: %v\n", err)
+				ws.option.Logger.PrintAndLog("static-webserv", "Web server failed to start", err)
 			}
 		}
 	}()
 
-	log.Println("Static Web Server started. Listeing on :" + ws.option.Port)
+	ws.option.Logger.PrintAndLog("static-webserv", "Static Web Server started. Listeing on :"+ws.option.Port, nil)
 	ws.isRunning = true
 	ws.option.Sysdb.Write("webserv", "enabled", true)
 	return nil
@@ -182,7 +187,7 @@ func (ws *WebServer) Stop() error {
 	if err := ws.server.Close(); err != nil {
 		return err
 	}
-
+	ws.option.Logger.PrintAndLog("static-webserv", "Static Web Server stopped", nil)
 	ws.isRunning = false
 	ws.option.Sysdb.Write("webserv", "enabled", false)
 	return nil

+ 7 - 19
reverseproxy.go

@@ -144,8 +144,9 @@ func ReverseProxtInit() {
 		//This must be done in go routine to prevent blocking on system startup
 		uptimeMonitor, _ = uptime.NewUptimeMonitor(&uptime.Config{
 			Targets:         GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter),
-			Interval:        300, //5 minutes
-			MaxRecordsStore: 288, //1 day
+			Interval:        300,              //5 minutes
+			MaxRecordsStore: 288,              //1 day
+			Logger:          SystemWideLogger, //Logger
 		})
 
 		SystemWideLogger.Println("Uptime Monitor background service started")
@@ -481,15 +482,6 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
 		proxyRateLimit = 1000
 	}
 
-	// Bypass WebSocket Origin Check
-	/*
-		strbpwsorg, _ := utils.PostPara(r, "bpwsorg")
-		if strbpwsorg == "" {
-			strbpwsorg = "false"
-		}
-		bypassWebsocketOriginCheck := (strbpwsorg == "true")
-	*/
-
 	//Load the previous basic auth credentials from current proxy rules
 	targetProxyEntry, err := dynamicProxyRouter.LoadProxy(rootNameOrMatchingDomain)
 	if err != nil {
@@ -499,11 +491,6 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
 
 	//Generate a new proxyEndpoint from the new config
 	newProxyEndpoint := dynamicproxy.CopyEndpoint(targetProxyEntry)
-	//TODO: Move these into dedicated module
-	//newProxyEndpoint.Domain = endpoint
-	//newProxyEndpoint.RequireTLS = useTLS
-	//newProxyEndpoint.SkipCertValidations = skipTlsValidation
-	//newProxyEndpoint.SkipWebSocketOriginCheck = bypassWebsocketOriginCheck
 	newProxyEndpoint.BypassGlobalTLS = bypassGlobalTLS
 	newProxyEndpoint.RequireBasicAuth = requireBasicAuth
 	newProxyEndpoint.RequireRateLimit = requireRateLimit
@@ -522,9 +509,6 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
 	//Save it to file
 	SaveReverseProxyConfig(newProxyEndpoint)
 
-	//Update uptime monitor
-	UpdateUptimeMonitorTargets()
-
 	utils.SendOK(w)
 }
 
@@ -882,6 +866,10 @@ func ReverseProxyToggleRuleSet(w http.ResponseWriter, r *http.Request) {
 		utils.SendErrorResponse(w, "unable to save updated rule")
 		return
 	}
+
+	//Update uptime monitor
+	UpdateUptimeMonitorTargets()
+
 	utils.SendOK(w)
 }
 

+ 1 - 0
start.go

@@ -139,6 +139,7 @@ func startupSequence() {
 		WebRoot:                *staticWebServerRoot,
 		EnableDirectoryListing: true,
 		EnableWebDirManager:    *allowWebFileManager,
+		Logger:                 SystemWideLogger,
 	})
 	//Restore the web server to previous shutdown state
 	staticWebServer.RestorePreviousState()

+ 9 - 0
upstreams.go

@@ -109,6 +109,9 @@ func ReverseProxyUpstreamAdd(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	//Update Uptime Monitor
+	UpdateUptimeMonitorTargets()
+
 	utils.SendOK(w)
 }
 
@@ -180,6 +183,9 @@ func ReverseProxyUpstreamUpdate(w http.ResponseWriter, r *http.Request) {
 		utils.SendErrorResponse(w, "Failed to save updated upstream config")
 		return
 	}
+
+	//Update Uptime Monitor
+	UpdateUptimeMonitorTargets()
 	utils.SendOK(w)
 }
 
@@ -270,5 +276,8 @@ func ReverseProxyUpstreamDelete(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	//Update uptime monitor
+	UpdateUptimeMonitorTargets()
+
 	utils.SendOK(w)
 }

+ 1 - 1
web/snippet/upstreams.html

@@ -75,7 +75,7 @@
                     </div>
                 </div>
                 <div class="ui message">
-                    <i class="ui blue info circle icon"></i> Round-robin load balancing algorithm will be used for upstreams with same weight. Set weight to 0 for fallback only.
+                    <i class="ui blue info circle icon"></i> Weighted random will be used for load-balancing. Set weight to 0 for fallback only.
                  </div>
             </div>
             <div class="ui tab basic segment" data-tab="newupstream">

+ 13 - 5
wrappers.go

@@ -115,7 +115,7 @@ func UpdateUptimeMonitorTargets() {
 			uptimeMonitor.ExecuteUptimeCheck()
 		}()
 
-		SystemWideLogger.PrintAndLog("Uptime", "Uptime monitor config updated", nil)
+		SystemWideLogger.PrintAndLog("uptime-monitor", "Uptime monitor config updated", nil)
 	}
 }
 
@@ -125,8 +125,12 @@ func GetUptimeTargetsFromReverseProxyRules(dp *dynamicproxy.Router) []*uptime.Ta
 
 	UptimeTargets := []*uptime.Target{}
 	for hostid, target := range hosts {
-		for _, origin := range target.ActiveOrigins {
-
+		if target.Disabled {
+			//Skip those proxy rules that is disabled
+			continue
+		}
+		isMultipleUpstreams := len(target.ActiveOrigins) > 1
+		for i, origin := range target.ActiveOrigins {
 			url := "http://" + origin.OriginIpOrDomain
 			protocol := "http"
 			if origin.RequireTLS {
@@ -135,9 +139,13 @@ func GetUptimeTargetsFromReverseProxyRules(dp *dynamicproxy.Router) []*uptime.Ta
 			}
 
 			//Add the root url
+			hostIdAndName := hostid
+			if isMultipleUpstreams {
+				hostIdAndName = hostIdAndName + " (upstream:" + strconv.Itoa(i) + ")"
+			}
 			UptimeTargets = append(UptimeTargets, &uptime.Target{
-				ID:        hostid,
-				Name:      hostid,
+				ID:        hostIdAndName,
+				Name:      hostIdAndName,
 				URL:       url,
 				Protocol:  protocol,
 				ProxyType: uptime.ProxyType_Host,