- New incident page documenting CT299 SFTPGo outage (02:18 AWST) - Root cause: swap exhaustion (43Gi, 100%) killed tailscaled; 5 stale lxc-attach PIDs blocked pct start - Resolution: killed PIDs 3037951/3334928/3352203/3402511/4004148, pct stop/start 299 - Updated current-state.md with Recent Changes (2026-09-02), bumped updated to 2026-09-04 - Updated log.md with incident entry - Updated index.md last-updated date No secrets written. Verified end-to-end: tailscale direct, SFTPGo WebAdmin HTTP 401, SFTP banner SSH-2.0-SFTPGo_2.7.0.
50 lines
1.7 KiB
Python
50 lines
1.7 KiB
Python
import http.server
|
|
import os
|
|
import socketserver
|
|
from pathlib import Path
|
|
|
|
class CleanURLHandler(http.server.SimpleHTTPRequestHandler):
|
|
def translate_path(self, path):
|
|
# Remove query string or fragment
|
|
if '?' in path:
|
|
path = path.split('?')[0]
|
|
if '#' in path:
|
|
path = path.split('#')[0]
|
|
|
|
# Serve index.html for directory paths
|
|
if path.endswith('/'):
|
|
path = path + 'index.html'
|
|
|
|
# If no extension and .html version exists, serve that
|
|
if not os.path.splitext(path)[1]:
|
|
html_path = Path(self.directory) / (path.lstrip('/') + '.html')
|
|
if html_path.is_file():
|
|
return str(html_path)
|
|
|
|
return super().translate_path(path)
|
|
|
|
def end_headers(self):
|
|
self.send_header('Access-Control-Allow-Origin', '*')
|
|
super().end_headers()
|
|
|
|
class CleanURLServer(socketserver.TCPServer):
|
|
allow_reuse_address = True # set BEFORE bind: permits instant rebind on restart
|
|
# (TIME-WAIT of prior instance would otherwise
|
|
# cause OSError 98 "Address already in use")
|
|
|
|
if __name__ == '__main__':
|
|
import argparse
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--directory', default='public')
|
|
parser.add_argument('--port', type=int, default=9120)
|
|
parser.add_argument('--bind', default='0.0.0.0')
|
|
args = parser.parse_args()
|
|
|
|
directory = Path(args.directory).resolve()
|
|
CleanURLHandler.directory = str(directory)
|
|
os.chdir(directory)
|
|
|
|
with CleanURLServer((args.bind, args.port), CleanURLHandler) as httpd:
|
|
print(f"Serving {directory} at http://{args.bind}:{args.port}")
|
|
httpd.serve_forever()
|