@@ -322,9 +322,108 @@ func (ac *AlvuConfig) StartServer() error {
322
322
return nil
323
323
}
324
324
325
- http .Handle ("/" , http .FileServer (http .Dir (ac .OutDir )))
325
+ normalizedPort := string (ac .PortNumber )
326
+
327
+ if ! strings .HasPrefix (normalizedPort , ":" ) {
328
+ normalizedPort = ":" + normalizedPort
329
+ }
330
+
331
+ http .Handle ("/" , http .HandlerFunc (ac .ServeHandler ))
326
332
ac .logger .Info (fmt .Sprintf ("Starting Server - %v:%v" , "http://localhost" , ac .PortNumber ))
327
- return http .ListenAndServe (fmt .Sprintf (":%v" , ac .PortNumber ), nil )
333
+
334
+ err := http .ListenAndServe (normalizedPort , nil )
335
+ if strings .Contains (err .Error (), "address already in use" ) {
336
+ ac .logger .Error ("port already in use, use another port with the `-port` flag instead" )
337
+ return err
338
+ }
339
+
340
+ return nil
341
+ }
342
+
343
+ func (ac * AlvuConfig ) ServeHandler (rw http.ResponseWriter , req * http.Request ) {
344
+ path := req .URL .Path
345
+
346
+ if path == "/" {
347
+ path = filepath .Join (ac .OutDir , "index.html" )
348
+ http .ServeFile (rw , req , path )
349
+ return
350
+ }
351
+
352
+ // check if the requested file already exists
353
+ file := filepath .Join (ac .OutDir , path )
354
+ info , err := os .Stat (file )
355
+
356
+ // if not, check if it's a directory
357
+ // and if it's a directory, we look for
358
+ // a index.html inside the directory to return instead
359
+ if err == nil {
360
+ if info .Mode ().IsDir () {
361
+ file = filepath .Join (ac .OutDir , path , "index.html" )
362
+ _ , err := os .Stat (file )
363
+ if err != nil {
364
+ ac .notFoundHandler (rw , req )
365
+ return
366
+ }
367
+ }
368
+
369
+ http .ServeFile (rw , req , file )
370
+ return
371
+ }
372
+
373
+ // if neither a directory or file was found
374
+ // try a secondary case where the file might be missing
375
+ // a `.html` extension for cleaner url so append a .html
376
+ // to look for the file.
377
+ if err != nil {
378
+ file := filepath .Join (ac .OutDir , normalizeStaticLookupPath (path ))
379
+ _ , err := os .Stat (file )
380
+
381
+ if err != nil {
382
+ ac .notFoundHandler (rw , req )
383
+ return
384
+ }
385
+
386
+ http .ServeFile (rw , req , file )
387
+ return
388
+ }
389
+
390
+ ac .notFoundHandler (rw , req )
391
+ }
392
+
393
+ func (ac * AlvuConfig ) notFoundHandler (w http.ResponseWriter , r * http.Request ) {
394
+ var notFoundPageExists bool
395
+ filePointer , err := os .Stat (filepath .Join (ac .OutDir , "404.html" ))
396
+ if err != nil {
397
+ if os .IsNotExist (err ) {
398
+ notFoundPageExists = false
399
+ }
400
+ }
401
+
402
+ if filePointer .Size () > 0 {
403
+ notFoundPageExists = true
404
+ }
405
+
406
+ if notFoundPageExists {
407
+ compiledNotFoundFile := filepath .Join (ac .OutDir , "404.html" )
408
+ notFoundFile , err := os .ReadFile (compiledNotFoundFile )
409
+ if err != nil {
410
+ http .Error (w , "404, Page not found...." , http .StatusNotFound )
411
+ return
412
+ }
413
+ w .WriteHeader (http .StatusNotFound )
414
+ w .Header ().Set ("Content-Type" , "text/html; charset=utf-8" )
415
+ w .Write (notFoundFile )
416
+ return
417
+ }
418
+
419
+ http .Error (w , "404, Page not found...." , http .StatusNotFound )
420
+ }
421
+
422
+ func normalizeStaticLookupPath (path string ) string {
423
+ if strings .HasSuffix (path , ".html" ) {
424
+ return path
425
+ }
426
+ return path + ".html"
328
427
}
329
428
330
429
func recursiveRead (dir string ) (filepaths []string , err error ) {
0 commit comments