diff options
| author | Barry Warsaw | 2015-08-25 00:33:14 +0000 |
|---|---|---|
| committer | Barry Warsaw | 2015-08-25 00:33:14 +0000 |
| commit | 352096f9903961915921ba2adfbe80d0467fdfb5 (patch) | |
| tree | 52b074c8de5e81cf2019b036022aa779a069c01c | |
| parent | c265a58eea8bb7abbdaa4cdbc0f25cafb1d78626 (diff) | |
| parent | 43627ee55a8bb9e876c8fcda3878326f72c8a5fa (diff) | |
| download | mailman-352096f9903961915921ba2adfbe80d0467fdfb5.tar.gz mailman-352096f9903961915921ba2adfbe80d0467fdfb5.tar.zst mailman-352096f9903961915921ba2adfbe80d0467fdfb5.zip | |
Merge branch 'issue142' into 'master'
Send REST server stderr to the http log file when the client hangs up
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.
Closes #142
See merge request !36
| -rw-r--r-- | src/mailman/rest/wsgiapp.py | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py index 94f654217..40757ee31 100644 --- a/src/mailman/rest/wsgiapp.py +++ b/src/mailman/rest/wsgiapp.py @@ -32,16 +32,27 @@ 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 log = logging.getLogger('mailman.http') _missing = object() SLASH = '/' +EMPTYSTRING = '' +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('REST server exception during request from %s', + client_address) + + class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): """Handler class which just logs output to the right place.""" @@ -49,6 +60,20 @@ 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 __init__(self): + self._buffer = [] + def write(self, message): + self._buffer.append(message) + def flush(self): + self._buffer.insert(0, 'REST request handler error:\n') + log.error(EMPTYSTRING.join(self._buffer)) + self._buffer = [] + return StderrLogger() + class SetAPIVersion: """Falcon middleware object that sets the api_version on resources.""" @@ -176,5 +201,6 @@ def make_server(): port = int(config.webservice.port) server = wsgi_server( host, port, make_application(), + server_class=AdminWSGIServer, handler_class=AdminWebServiceWSGIRequestHandler) return server |
