|
@@ -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()
|
|
|
+}
|