mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-06 07:37:21 +02:00

- Rewritten the logger to make it more apache log parser friendly - Fixed uptime not updating after upstream change bug - Added SSO page (wip) - Added log viewer
206 lines
5.1 KiB
Go
206 lines
5.1 KiB
Go
package webserv
|
|
|
|
import (
|
|
"embed"
|
|
_ "embed"
|
|
"errors"
|
|
"fmt"
|
|
"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"
|
|
)
|
|
|
|
/*
|
|
Static Web Server package
|
|
|
|
This module host a static web server
|
|
*/
|
|
|
|
//go:embed templates/*
|
|
var templates embed.FS
|
|
|
|
type WebServerOptions struct {
|
|
Port string //Port for listening
|
|
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
|
|
}
|
|
|
|
type WebServer struct {
|
|
FileManager *filemanager.FileManager
|
|
|
|
mux *http.ServeMux
|
|
server *http.Server
|
|
option *WebServerOptions
|
|
isRunning bool
|
|
mu sync.Mutex
|
|
}
|
|
|
|
// 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 {
|
|
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)
|
|
}
|
|
|
|
}
|
|
|
|
//Create a new file manager if it is enabled
|
|
var newDirManager *filemanager.FileManager
|
|
if options.EnableWebDirManager {
|
|
fm := filemanager.NewFileManager(filepath.Join(options.WebRoot, "/html"))
|
|
newDirManager = fm
|
|
}
|
|
|
|
//Create new table to store the config
|
|
options.Sysdb.NewTable("webserv")
|
|
return &WebServer{
|
|
mux: http.NewServeMux(),
|
|
FileManager: newDirManager,
|
|
option: options,
|
|
isRunning: false,
|
|
mu: sync.Mutex{},
|
|
}
|
|
}
|
|
|
|
// Restore the configuration to previous config
|
|
func (ws *WebServer) RestorePreviousState() {
|
|
//Set the port
|
|
port := ws.option.Port
|
|
ws.option.Sysdb.Read("webserv", "port", &port)
|
|
ws.option.Port = port
|
|
|
|
//Set the enable directory list
|
|
enableDirList := ws.option.EnableDirectoryListing
|
|
ws.option.Sysdb.Read("webserv", "dirlist", &enableDirList)
|
|
ws.option.EnableDirectoryListing = enableDirList
|
|
|
|
//Check the running state
|
|
webservRunning := true
|
|
ws.option.Sysdb.Read("webserv", "enabled", &webservRunning)
|
|
if webservRunning {
|
|
ws.Start()
|
|
} else {
|
|
ws.Stop()
|
|
}
|
|
|
|
}
|
|
|
|
// 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")
|
|
}
|
|
|
|
if ws.isRunning {
|
|
if err := ws.Stop(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
ws.option.Port = port
|
|
ws.server.Addr = ":" + port
|
|
|
|
err := ws.Start()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ws.option.Logger.PrintAndLog("static-webserv", "Listening port updated to "+port, nil)
|
|
ws.option.Sysdb.Write("webserv", "port", port)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Get current using port in options
|
|
func (ws *WebServer) GetListeningPort() string {
|
|
return ws.option.Port
|
|
}
|
|
|
|
// 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(filepath.Join(ws.option.WebRoot, "html")))
|
|
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 {
|
|
ws.option.Logger.PrintAndLog("static-webserv", "Web server failed to start", err)
|
|
}
|
|
}
|
|
}()
|
|
|
|
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
|
|
}
|
|
|
|
// 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.option.Logger.PrintAndLog("static-webserv", "Static Web Server stopped", nil)
|
|
ws.isRunning = false
|
|
ws.option.Sysdb.Write("webserv", "enabled", false)
|
|
return nil
|
|
}
|
|
|
|
// UpdateDirectoryListing enables or disables directory listing.
|
|
func (ws *WebServer) UpdateDirectoryListing(enable bool) {
|
|
ws.option.EnableDirectoryListing = enable
|
|
ws.option.Sysdb.Write("webserv", "dirlist", enable)
|
|
}
|
|
|
|
// Close stops the web server without returning an error.
|
|
func (ws *WebServer) Close() {
|
|
ws.Stop()
|
|
}
|