Skip to content

Commit

Permalink
Fixed #4444 - Made runserver suppress 'broken pipe' errors
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dracos authored and timgraham committed Nov 28, 2014
1 parent 9e80c5f commit 9253042
Showing 1 changed file with 38 additions and 0 deletions.
38 changes: 38 additions & 0 deletions django/core/servers/basehttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"""

Expand All @@ -75,6 +80,19 @@ def server_bind(self):
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):

Expand Down Expand Up @@ -134,6 +152,26 @@ def get_environ(self):

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)
Expand Down

0 comments on commit 9253042

Please sign in to comment.