Commit 9253042d authored by Matthew Somerville's avatar Matthew Somerville Committed by Tim Graham
Browse files

Fixed #4444 - Made runserver suppress 'broken pipe' errors

One handler in WSGIServer, to catch the error when raised from
SocketServer.BaseServer's finish_request, and one in WSGIRequestHandler
(by creating a subclass of ServerHandler), to catch the error when
raised in wsgiref.handlers.BaseHandler's finish_response.
parent 9e80c5f4
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -60,6 +60,11 @@ def get_internal_wsgi_application():
                    sys.exc_info()[2])


def is_broken_pipe_error():
    exc_type, exc_value = sys.exc_info()[:2]
    return issubclass(exc_type, socket.error) and exc_value.args[0] == 32


class WSGIServer(simple_server.WSGIServer, object):
    """BaseHTTPServer that implements the Python WSGI protocol"""

@@ -75,6 +80,19 @@ class WSGIServer(simple_server.WSGIServer, object):
        super(WSGIServer, self).server_bind()
        self.setup_environ()

    def handle_error(self, request, client_address):
        if is_broken_pipe_error():
            sys.stderr.write("- Broken pipe from %s\n" % (client_address,))
        else:
            super(WSGIServer, self).handle_error(request, client_address)


class ServerHandler(simple_server.ServerHandler):
    def handle_error(self):
        # Ignore broken pipe errors, otherwise pass on
        if not is_broken_pipe_error():
            super(ServerHandler, self).handle_error()


class WSGIRequestHandler(simple_server.WSGIRequestHandler, object):

@@ -134,6 +152,26 @@ class WSGIRequestHandler(simple_server.WSGIRequestHandler, object):

        return env

    def handle(self):
        """Copy of WSGIRequestHandler, but with different ServerHandler"""

        self.raw_requestline = self.rfile.readline(65537)
        if len(self.raw_requestline) > 65536:
            self.requestline = ''
            self.request_version = ''
            self.command = ''
            self.send_error(414)
            return

        if not self.parse_request():  # An error code has been sent, just exit
            return

        handler = ServerHandler(
            self.rfile, self.wfile, self.get_stderr(), self.get_environ()
        )
        handler.request_handler = self      # backpointer for logging
        handler.run(self.server.get_app())


def run(addr, port, wsgi_handler, ipv6=False, threading=False):
    server_address = (addr, port)