Procházet zdrojové kódy

auto update script executed

Toby Chui před 1 rokem
rodič
revize
59e449e109
5 změnil soubory, kde provedl 177 přidání a 0 odebrání
  1. 4 0
      main.go
  2. 9 0
      mod/webserv/handler.go
  3. 20 0
      mod/webserv/middleware.go
  4. 18 0
      mod/webserv/utils.go
  5. 126 0
      mod/webserv/webserv.go

+ 4 - 0
main.go

@@ -30,6 +30,7 @@ import (
 	"imuslab.com/zoraxy/mod/tlscert"
 	"imuslab.com/zoraxy/mod/uptime"
 	"imuslab.com/zoraxy/mod/utils"
+	"imuslab.com/zoraxy/mod/webserv"
 )
 
 // General flags
@@ -41,6 +42,8 @@ var ztAuthToken = flag.String("ztauth", "", "ZeroTier authtoken for the local no
 var ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port")
 var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)")
 var enableHighSpeedGeoIPLookup = flag.Bool("fastgeoip", false, "Enable high speed geoip lookup, require 1GB extra memory (Not recommend for low end devices)")
+var staticWebServerRoot = flag.String("webroot", "./web", "Static web server root folder. Only allow chnage in start paramters")
+
 var (
 	name        = "Zoraxy"
 	version     = "2.6.7"
@@ -73,6 +76,7 @@ var (
 	tcpProxyManager    *tcpprox.Manager        //TCP Proxy Manager
 	acmeHandler        *acme.ACMEHandler       //Handler for ACME Certificate renew
 	acmeAutoRenewer    *acme.AutoRenewer       //Handler for ACME auto renew ticking
+	staticWebServer    *webserv.WebServer      //Static web server for hosting simple stuffs
 
 	//Helper modules
 	EmailSender    *email.Sender        //Email sender that handle email sending

+ 9 - 0
mod/webserv/handler.go

@@ -0,0 +1,9 @@
+package webserv
+
+/*
+	Handler.go
+
+	Handler for web server options change
+	web server is directly listening to the TCP port
+	handlers in this script are for setting change only
+*/

+ 20 - 0
mod/webserv/middleware.go

@@ -0,0 +1,20 @@
+package webserv
+
+import (
+	"net/http"
+	"strings"
+)
+
+// File server middleware to handle directory listing (and future expansion)
+func (ws *WebServer) fsMiddleware(h http.Handler) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if ws.option.EnableDirectoryListing {
+			if strings.HasSuffix(r.URL.Path, "/") {
+				http.NotFound(w, r)
+				return
+			}
+		}
+
+		h.ServeHTTP(w, r)
+	})
+}

+ 18 - 0
mod/webserv/utils.go

@@ -0,0 +1,18 @@
+package webserv
+
+import (
+	"net"
+)
+
+// IsPortInUse checks if a port is in use.
+func IsPortInUse(port string) bool {
+	listener, err := net.Listen("tcp", "localhost:"+port)
+	if err != nil {
+		// If there was an error, the port is in use.
+		return true
+	}
+	defer listener.Close()
+
+	// No error means the port is available.
+	return false
+}

+ 126 - 0
mod/webserv/webserv.go

@@ -0,0 +1,126 @@
+package webserv
+
+import (
+	"errors"
+	"fmt"
+	"net/http"
+	"sync"
+)
+
+/*
+	Static Web Server package
+
+	This module host a static web server
+*/
+
+type WebServerOptions struct {
+	Port                   string //Port for listening
+	EnableDirectoryListing bool   //Enable listing of directory
+	WebRoot                string //Folder for stroing the static web folders
+}
+type WebServer struct {
+	mux       *http.ServeMux
+	server    *http.Server
+	option    *WebServerOptions
+	isRunning bool
+	mu        sync.Mutex
+}
+
+// NewWebServer creates a new WebServer instance.
+func NewWebServer(options *WebServerOptions) *WebServer {
+	return &WebServer{
+		mux:       http.NewServeMux(),
+		option:    options,
+		isRunning: false,
+		mu:        sync.Mutex{},
+	}
+}
+
+// ChangePort changes the server's port.
+func (ws *WebServer) ChangePort(port string) error {
+	ws.mu.Lock()
+	defer ws.mu.Unlock()
+
+	if ws.isRunning {
+		if err := ws.Stop(); err != nil {
+			return err
+		}
+	}
+
+	ws.option.Port = port
+	ws.server.Addr = ":" + port
+
+	return nil
+}
+
+// Start starts the web server.
+func (ws *WebServer) Start() error {
+	ws.mu.Lock()
+	defer ws.mu.Unlock()
+
+	//Check if server already running
+	if ws.isRunning {
+		return fmt.Errorf("web server is already running")
+	}
+
+	//Check if the port is usable
+	if IsPortInUse(ws.option.Port) {
+		return errors.New("Port already in use or access denied by host OS")
+	}
+
+	//Dispose the old mux and create a new one
+	ws.mux = http.NewServeMux()
+
+	//Create a static web server
+	fs := http.FileServer(http.Dir(ws.option.WebRoot))
+	ws.mux.Handle("/", ws.fsMiddleware(fs))
+
+	ws.server = &http.Server{
+		Addr:    ":" + ws.option.Port,
+		Handler: ws.mux,
+	}
+
+	go func() {
+		if err := ws.server.ListenAndServe(); err != nil {
+			if err != http.ErrServerClosed {
+				fmt.Printf("Web server error: %v\n", err)
+			}
+		}
+	}()
+
+	ws.isRunning = true
+
+	return nil
+}
+
+// Stop stops the web server.
+func (ws *WebServer) Stop() error {
+	ws.mu.Lock()
+	defer ws.mu.Unlock()
+
+	if !ws.isRunning {
+		return fmt.Errorf("web server is not running")
+	}
+
+	if err := ws.server.Close(); err != nil {
+		return err
+	}
+
+	ws.isRunning = false
+
+	return nil
+}
+
+// UpdateDirectoryListing enables or disables directory listing.
+func (ws *WebServer) UpdateDirectoryListing(enable bool) {
+	ws.mu.Lock()
+	defer ws.mu.Unlock()
+
+	ws.option.EnableDirectoryListing = enable
+
+}
+
+// Close stops the web server without returning an error.
+func (ws *WebServer) Close() {
+	ws.Stop()
+}