From 3f550a975a0def1dafbd4e060b01f0553ef2967f Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Sun, 23 Aug 2015 20:44:14 -0400 Subject: When the client hangs up, we can't actually catch the BrokenPipeError because of the way Python stdlib's wsgiref.simple_server is structured. However, we can ensure that the error messages won't get printed to stderr, but to our http log file instead. --- src/mailman/rest/wsgiapp.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py index 94f654217..06bd9d2b9 100644 --- a/src/mailman/rest/wsgiapp.py +++ b/src/mailman/rest/wsgiapp.py @@ -32,7 +32,7 @@ from falcon.routing import create_http_method_map from mailman.config import config from mailman.database.transaction import transactional from mailman.rest.root import Root -from wsgiref.simple_server import WSGIRequestHandler +from wsgiref.simple_server import WSGIRequestHandler, WSGIServer from wsgiref.simple_server import make_server as wsgi_server @@ -42,6 +42,16 @@ SLASH = '/' +class AdminWSGIServer(WSGIServer): + """Server class that integrates error handling with our log files.""" + + def handle_error(self, request, client_address): + # Interpose base class method so that the exception gets printed to + # our log file rather than stderr. + log.exception('Exception happened during request from %s', + client_address) + + class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): """Handler class which just logs output to the right place.""" @@ -49,6 +59,16 @@ class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): """See `BaseHTTPRequestHandler`.""" log.info('%s - - %s', self.address_string(), format % args) + def get_stderr(self): + # Return a fake stderr object that will actually write its output to + # the log file. + class StderrLogger: + def write(self, message): + log.exception('Client error') + def flush(self): + pass + return StderrLogger() + class SetAPIVersion: """Falcon middleware object that sets the api_version on resources.""" @@ -176,5 +196,6 @@ def make_server(): port = int(config.webservice.port) server = wsgi_server( host, port, make_application(), + server_class=AdminWSGIServer, handler_class=AdminWebServiceWSGIRequestHandler) return server -- cgit v1.2.3-70-g09d2 From 43627ee55a8bb9e876c8fcda3878326f72c8a5fa Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Mon, 24 Aug 2015 20:05:20 -0400 Subject: Refine REST server and request handler exception handling. --- src/mailman/rest/wsgiapp.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py index 06bd9d2b9..40757ee31 100644 --- a/src/mailman/rest/wsgiapp.py +++ b/src/mailman/rest/wsgiapp.py @@ -39,6 +39,7 @@ from wsgiref.simple_server import make_server as wsgi_server log = logging.getLogger('mailman.http') _missing = object() SLASH = '/' +EMPTYSTRING = '' @@ -48,7 +49,7 @@ class AdminWSGIServer(WSGIServer): def handle_error(self, request, client_address): # Interpose base class method so that the exception gets printed to # our log file rather than stderr. - log.exception('Exception happened during request from %s', + log.exception('REST server exception during request from %s', client_address) @@ -63,10 +64,14 @@ class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): # Return a fake stderr object that will actually write its output to # the log file. class StderrLogger: + def __init__(self): + self._buffer = [] def write(self, message): - log.exception('Client error') + self._buffer.append(message) def flush(self): - pass + self._buffer.insert(0, 'REST request handler error:\n') + log.error(EMPTYSTRING.join(self._buffer)) + self._buffer = [] return StderrLogger() -- cgit v1.2.3-70-g09d2