@@ -2,11 +2,15 @@ package web
22
33import (
44 "context"
5+ "crypto/tls"
56 "fmt"
67 "log"
8+ "log/slog"
9+ "net"
710 "net/http"
811 "os"
912 "path/filepath"
13+ "strings"
1014 "sync"
1115 "text/template"
1216 "time"
@@ -222,7 +226,14 @@ func serveTemplate(w http.ResponseWriter, r *http.Request) {
222226 }
223227}
224228
225- func Listen (webPort int , webHttpsPort int , wg * sync.WaitGroup , webSocketHandler func (* websocket.Conn )) {
229+ func Listen (wg * sync.WaitGroup , webSocketHandler func (* websocket.Conn )) {
230+
231+ networkConfig := configs .GetNetworkConfig ()
232+
233+ if networkConfig .HttpPort == 0 && networkConfig .HttpsPort == 0 {
234+ slog .Error (`Web` , "error" , "No ports defined. No web server will be started." )
235+ return
236+ }
226237
227238 // Routing
228239 // Basic homepage
@@ -294,45 +305,97 @@ func Listen(webPort int, webHttpsPort int, wg *sync.WaitGroup, webSocketHandler
294305 doBasicAuth (roomData ),
295306 ))
296307
297- // HTTP Server
298- wg .Add (1 )
299- httpServer = & http.Server {Addr : fmt .Sprintf (`:%d` , webPort )}
300- go func () {
308+ //
309+ // Http server start up
310+ //
301311
302- mudlog . Info ( "Starting http server" , "webport" , webPort )
312+ if networkConfig . HttpPort > 0 {
303313
304- defer wg .Done ()
305- if err := httpServer .ListenAndServe (); err != nil && err != http .ErrServerClosed {
306- mudlog .Error ("Error starting web server" , "error" , err )
314+ httpServer = & http.Server {
315+ Addr : fmt .Sprintf (`:%d` , networkConfig .HttpPort ),
307316 }
308- }()
309317
310- if webHttpsPort > 0 {
318+ if networkConfig . HttpsRedirect && networkConfig . HttpsPort != 0 {
311319
312- filePaths := configs . GetFilePathsConfig ()
320+ var redirectHandler http. HandlerFunc = func ( w http. ResponseWriter , r * http. Request ) {
313321
314- certFile := ``
315- keyFile := ``
322+ host := r .Host
323+
324+ // If the host header includes a port (e.g. "example.com:80"), strip it out.
325+ if strings .Contains (host , ":" ) {
326+ host , _ , _ = net .SplitHostPort (host )
327+ }
328+
329+ // Build the target URL with your known HTTPS port (443 in this case).
330+ target := fmt .Sprintf ("https://%s:%d%s" , host , networkConfig .HttpsPort , r .RequestURI )
331+
332+ http .Redirect (w , r , target , http .StatusMovedPermanently )
333+
334+ }
335+
336+ httpServer .Handler = redirectHandler
316337
317- if _ , err := os .Stat (string (filePaths .HttpsCertFile )); err == nil {
318- certFile = string (filePaths .HttpsCertFile )
319- }
320- if _ , err := os .Stat (string (filePaths .HttpsKeyFile )); err == nil {
321- keyFile = string (filePaths .HttpsKeyFile )
322338 }
323339
324- if certFile != `` && keyFile != `` {
325- wg .Add (1 )
326- httpsServer = & http.Server {Addr : fmt .Sprintf (`:%d` , webHttpsPort )}
327- go func () {
340+ // HTTP Server
341+ wg .Add (1 )
342+
343+ mudlog .Info ("HTTP" , "stage" , "Starting http server" , "port" , networkConfig .HttpPort )
344+ go func () {
345+ defer wg .Done ()
346+
347+ if err := httpServer .ListenAndServe (); err != nil && err != http .ErrServerClosed {
348+ mudlog .Error ("HTTP" , "error" , fmt .Errorf ("Error starting web server: %w" , err ))
349+ }
350+ }()
351+ }
352+
353+ //
354+ // Https server start up
355+ //
328356
329- mudlog . Info ( "Starting https server" , "webHttpsPort" , webHttpsPort )
357+ if networkConfig . HttpsPort > 0 {
330358
331- defer wg .Done ()
332- if err := httpsServer .ListenAndServeTLS (certFile , keyFile ); err != nil && err != http .ErrServerClosed {
333- mudlog .Error ("Error starting HTTPS web server" , "error" , err )
359+ filePaths := configs .GetFilePathsConfig ()
360+
361+ if len (filePaths .HttpsCertFile ) == 0 || len (filePaths .HttpsKeyFile ) == 0 {
362+
363+ mudlog .Info ("HTTPS" , "stage" , "skipping" , "error" , "Undefined key file" , "Public Cert" , filePaths .HttpsCertFile , "Private Key" , filePaths .HttpsKeyFile )
364+
365+ } else {
366+
367+ if filePaths .HttpsCertFile != `` && filePaths .HttpsKeyFile != `` {
368+
369+ mudlog .Info ("HTTPS" , "stage" , "Validating public/private key pair" , "Public Cert" , filePaths .HttpsCertFile , "Private Key" , filePaths .HttpsKeyFile )
370+
371+ cert , err := tls .LoadX509KeyPair (string (filePaths .HttpsCertFile ), string (filePaths .HttpsKeyFile ))
372+
373+ if err != nil {
374+
375+ mudlog .Error ("HTTPS" , "error" , fmt .Errorf ("Error loading certificate and key: %w" , err ))
376+
377+ } else {
378+
379+ tlsConfig := & tls.Config {
380+ Certificates : []tls.Certificate {cert },
381+ }
382+
383+ wg .Add (1 )
384+
385+ httpsServer = & http.Server {
386+ Addr : fmt .Sprintf (`:%d` , networkConfig .HttpsPort ),
387+ TLSConfig : tlsConfig ,
388+ }
389+
390+ mudlog .Info ("HTTPS" , "stage" , "Starting https server" , "port" , networkConfig .HttpsPort )
391+ go func () {
392+ defer wg .Done ()
393+ if err := httpsServer .ListenAndServeTLS ("" , "" ); err != nil && err != http .ErrServerClosed {
394+ mudlog .Error ("HTTPS" , "error" , fmt .Errorf ("Error starting HTTPS web server: %w" , err ))
395+ }
396+ }()
334397 }
335- }()
398+ }
336399 }
337400 }
338401
@@ -357,13 +420,17 @@ func Shutdown() {
357420
358421 if httpServer != nil {
359422 if err := httpServer .Shutdown (ctx ); err != nil {
360- log .Printf ("HTTP server shutdown failed:%+v" , err )
423+ mudlog .Error ("HTTP" , "error" , fmt .Errorf ("HTTP server shutdown failed: %w" , err ))
424+ } else {
425+ mudlog .Info ("HTTPS" , "stage" , "stopped" )
361426 }
362427 }
363428
364429 if httpsServer != nil {
365430 if err := httpsServer .Shutdown (ctx ); err != nil {
366- log .Printf ("HTTPS server shutdown failed:%+v" , err )
431+ mudlog .Error ("HTTPS" , "error" , fmt .Errorf ("HTTP server shutdown failed: %w" , err ))
432+ } else {
433+ mudlog .Info ("HTTPS" , "stage" , "stopped" )
367434 }
368435 }
369436}
0 commit comments