@@ -20,7 +20,9 @@ import os
20
20
import posixpath
21
21
import re
22
22
import shutil
23
+ import socket
23
24
import socketserver
25
+ import subprocess
24
26
import sys
25
27
import time
26
28
import urllib .error
@@ -218,8 +220,7 @@ class SimpleHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
218
220
f .write (b"<html>\n " )
219
221
f .write (
220
222
(
221
- '<meta http-equiv="Content-Type" '
222
- 'content="text/html; charset=%s">' % enc
223
+ '<meta http-equiv="Content-Type" content="text/html; charset=%s">' % enc
223
224
).encode (enc )
224
225
)
225
226
f .write (("<title>Directory listing for %s</title>\n " % displaypath ).encode (enc ))
@@ -257,8 +258,15 @@ class SimpleHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
257
258
dirimage = "data:image/gif;base64,R0lGODlhGAAYAMIAAP///7+/v7u7u1ZWVTc3NwAAAAAAAAAAACH+RFRoaXMgaWNvbiBpcyBpbiB0aGUgcHVibGljIGRvbWFpbi4gMTk5NSBLZXZpbiBIdWdoZXMsIGtldmluaEBlaXQuY29tACH5BAEAAAEALAAAAAAYABgAAANdGLrc/jAuQaulQwYBuv9cFnFfSYoPWXoq2qgrALsTYN+4QOg6veFAG2FIdMCCNgvBiAxWlq8mUseUBqGMoxWArW1xXYXWGv59b+WxNH1GV9vsNvd9jsMhxLw+70gAADs="
258
259
fullname = os .path .join (path , name )
259
260
displayname = linkname = name
260
- fsize = fbytes (os .path .getsize (fullname ))
261
- created_date = time .ctime (os .path .getctime (fullname ))
261
+
262
+ try :
263
+ fsize = fbytes (os .path .getsize (fullname ))
264
+ created_date = time .ctime (os .path .getctime (fullname ))
265
+ except (FileNotFoundError , OSError ):
266
+ # Handle dangling symlinks and other file access errors
267
+ fsize = "?"
268
+ created_date = "?"
269
+
262
270
# Append / for directories or @ for symbolic links
263
271
if os .path .isdir (fullname ):
264
272
dirimage = "data:image/png;base64,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"
@@ -372,7 +380,7 @@ parser.add_argument(
372
380
"-b" ,
373
381
default = "" ,
374
382
metavar = "ADDRESS" ,
375
- help = "Specify alternate bind address " " [default: all interfaces]" ,
383
+ help = "Specify alternate bind address [default: all interfaces]" ,
376
384
)
377
385
parser .add_argument (
378
386
"port" ,
@@ -388,14 +396,53 @@ PORT = args.port
388
396
BIND = args .bind
389
397
HOST = BIND
390
398
391
- if HOST == "" :
392
- HOST = "localhost"
399
+
400
+ def get_ip_addresses ():
401
+ """Get all IPv4 addresses for this host."""
402
+ addresses = []
403
+
404
+ try :
405
+ # Try ip addr first (modern systems)
406
+ output = subprocess .check_output (["ip" , "addr" ], text = True )
407
+ for line in output .split ("\n " ):
408
+ if "inet " in line and "scope global" in line :
409
+ ip = line .split ()[1 ].split ("/" )[0 ]
410
+ addresses .append (ip )
411
+ except (subprocess .CalledProcessError , FileNotFoundError ):
412
+ try :
413
+ # Fall back to ifconfig
414
+ output = subprocess .check_output (["ifconfig" ], text = True )
415
+ for line in output .split ("\n " ):
416
+ if "inet " in line and "broadcast" in line :
417
+ ip = line .split ()[1 ]
418
+ addresses .append (ip )
419
+ except (subprocess .CalledProcessError , FileNotFoundError ):
420
+ # If both fail, just use socket to get hostname IP
421
+ try :
422
+ hostname_ip = socket .gethostbyname (socket .gethostname ())
423
+ if hostname_ip != "127.0.0.1" :
424
+ addresses .append (hostname_ip )
425
+ except socket .gaierror :
426
+ pass
427
+
428
+ # Always include localhost
429
+ if "127.0.0.1" not in addresses :
430
+ addresses .append ("127.0.0.1" )
431
+
432
+ return sorted (addresses ) # Sort for consistent output
433
+
434
+
435
+ if HOST in ("" , "0.0.0.0" ):
436
+ HOST = "0.0.0.0" # Listen on all interfaces
437
+ print ("Server accessible at:" )
438
+ for addr in get_ip_addresses ():
439
+ print (f" http://{ addr } :{ PORT } /" )
440
+ else :
441
+ print (f"Server accessible at: http://{ HOST } :{ PORT } /" )
393
442
394
443
Handler = SimpleHTTPRequestHandler
395
444
396
445
with socketserver .TCPServer ((BIND , PORT ), Handler ) as httpd :
397
- serve_message = "Serving HTTP on {host} port {port} (http://{host}:{port}/) ..."
398
- print (serve_message .format (host = HOST , port = PORT ))
399
446
try :
400
447
httpd .serve_forever ()
401
448
except KeyboardInterrupt :
0 commit comments