This commit is contained in:
2026-01-25 13:20:58 -06:00
parent 3884abc695
commit 2d9aba7e04
37 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""
HTTP health check server
"""
import sys
import json
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler
from datetime import datetime
from logger import log
from config import config
class SilentHTTPServer(HTTPServer):
"""HTTP Server that ignores connection reset errors from scanners"""
def handle_error(self, request, client_address):
exc_type = sys.exc_info()[0]
if exc_type in (ConnectionResetError, BrokenPipeError, ConnectionAbortedError):
pass # Silently ignore - these are just scanners/health checks disconnecting
else:
log(f"Health server error from {client_address[0]}: {sys.exc_info()[1]}", 'WARNING')
class HealthHandler(BaseHTTPRequestHandler):
"""Health check request handler"""
worker = None # Will be set by start_health_server()
dynamodb_available = False
def do_GET(self):
if self.path == '/health' or self.path == '/':
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
status = {
'status': 'healthy',
'domains': len(self.worker.queue_urls) if self.worker else 0,
'domain_list': list(self.worker.queue_urls.keys()) if self.worker else [],
'dynamodb': self.dynamodb_available,
'features': {
'bounce_rewriting': True,
'auto_reply': self.dynamodb_available,
'forwarding': self.dynamodb_available,
'blocklist': self.dynamodb_available,
'lmtp': config.lmtp_enabled
},
'timestamp': datetime.utcnow().isoformat()
}
self.wfile.write(json.dumps(status, indent=2).encode())
elif self.path == '/domains':
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
domain_list = list(self.worker.queue_urls.keys()) if self.worker else []
self.wfile.write(json.dumps(domain_list).encode())
else:
self.send_response(404)
self.end_headers()
def log_message(self, format, *args):
pass # Suppress HTTP access logs
def start_health_server(worker, dynamodb_available: bool):
"""
Start HTTP health check server
Args:
worker: UnifiedWorker instance
dynamodb_available: Whether DynamoDB is available
"""
# Set class attributes for handler
HealthHandler.worker = worker
HealthHandler.dynamodb_available = dynamodb_available
server = SilentHTTPServer(('0.0.0.0', config.health_port), HealthHandler)
thread = threading.Thread(target=server.serve_forever, daemon=True, name='health-server')
thread.start()
log(f"Health server on port {config.health_port}")