fix: the web service, the metrics service and the bootstrap server log a failure in one line instead of a traceback, and nothing when a client goes away.
Release / release (push) Successful in 17s

This commit is contained in:
slawek committed 2026-10-30 02:01:27 +01:00
1 parent 3de030b06b
commit dd489e65aa
3 files changed
+38 -3

No files matched your search

+10
View File
@@ -1,3 +1,13 @@
vpn-router (0.37.2-1) unstable; urgency=medium
fix: the web service, the metrics service and the bootstrap server log a failure in one line instead of a traceback, and nothing when a client goes away.
* A request whose client closed the connection is no longer logged.
* Any other failure of a request, a thread or the service is logged in
one line with the exception's type and message.
-- Slawomir Koszewski <slawek@koszewscy.waw.pl> Fri, 30 Oct 2026 01:59:19 +0100
vpn-router (0.37.1-1) unstable; urgency=medium
fix: /config answers the OpenID Provider's state and issuer.
@@ -8,6 +8,7 @@ the logs.
"""
import subprocess
import sys
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
PORT = 17081
@@ -51,5 +52,15 @@ class Handler(BaseHTTPRequestHandler):
self.wfile.write(body)
def failed(request, client_address):
"""Log a failed request in one line, and nothing when the client went away."""
failure = sys.exc_info()[1]
if not isinstance(failure, ConnectionError):
print(f'a request from {client_address[0]} failed: {type(failure).__name__}: {failure}', file=sys.stderr, flush=True)
if __name__ == '__main__':
ThreadingHTTPServer(('', PORT), Handler).serve_forever()
sys.excepthook = lambda kind, value, _: print(f'failed: {kind.__name__}: {value}', file=sys.stderr, flush=True)
server = ThreadingHTTPServer(('', PORT), Handler)
server.handle_error = failed
server.serve_forever()
@@ -4,6 +4,7 @@ Only the Python standard library is used, so the bootstrap server, which must ru
is broken, can use it.
"""
import sys
import threading
import time
from http.server import ThreadingHTTPServer
@@ -14,9 +15,21 @@ def serve(wanted, handler, log, interval):
wanted answers ([(address, port), ...], '') or ([], the reason not to listen). A server whose
place is no longer wanted is stopped, and a new one listens at each new place; a place that
cannot be bound is tried again the next round. Every new message is logged with log. Does
not return.
cannot be bound is tried again the next round. Every new message is logged with log. A request
whose client went away is not logged; any other exception a request, a thread or the process
does not handle is logged with log in one line, without a traceback. Does not return.
"""
def failed(request, client_address):
failure = sys.exc_info()[1]
if not isinstance(failure, ConnectionError):
log(f'a request from {client_address[0]} failed: {type(failure).__name__}: {failure}')
def thread_failed(hook):
if not issubclass(hook.exc_type, (SystemExit, ConnectionError)):
log(f'{hook.thread.name if hook.thread else "a thread"} failed: {hook.exc_type.__name__}: {hook.exc_value}')
threading.excepthook = thread_failed
sys.excepthook = lambda kind, value, _: log(f'failed: {kind.__name__}: {value}')
servers, reported = {}, None
while True:
targets, reason = wanted()
@@ -34,6 +47,7 @@ def serve(wanted, handler, log, interval):
except OSError as exc:
messages.append(f'cannot listen on {target[0]}:{target[1]}: {exc}')
continue
server.handle_error = failed
thread = threading.Thread(target=server.serve_forever, name=f'server {target[0]}', daemon=True)
thread.start()
servers[target] = (server, thread)