From 7d4916f01462de09cb58853d9de2e85777c2ad5b Mon Sep 17 00:00:00 2001 From: Sergey Shepelev Date: Fri, 9 Aug 2013 14:25:10 +0400 Subject: [PATCH] wsgi: configurable socket_timeout --- eventlet/wsgi.py | 13 ++++++++++--- tests/wsgi_test.py | 11 +++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/eventlet/wsgi.py b/eventlet/wsgi.py index 59186e5..1a99b78 100644 --- a/eventlet/wsgi.py +++ b/eventlet/wsgi.py @@ -540,7 +540,8 @@ class Server(BaseHTTPServer.HTTPServer): log_output=True, log_format=DEFAULT_LOG_FORMAT, url_length_limit=MAX_REQUEST_LINE, - debug=True): + debug=True, + socket_timeout=None): self.outstanding_requests = 0 self.socket = socket @@ -561,6 +562,7 @@ class Server(BaseHTTPServer.HTTPServer): self.log_format = log_format self.url_length_limit = url_length_limit self.debug = debug + self.socket_timeout = socket_timeout def get_environ(self): d = { @@ -623,7 +625,8 @@ def server(sock, site, log_output=True, log_format=DEFAULT_LOG_FORMAT, url_length_limit=MAX_REQUEST_LINE, - debug=True): + debug=True, + socket_timeout=None): """Start up a WSGI server handling requests from the supplied server socket. This function loops forever. The *sock* object will be closed after server exits, but the underlying file descriptor will remain open, so if you have a dup() of *sock*, @@ -645,6 +648,7 @@ def server(sock, site, :param log_format: A python format string that is used as the template to generate log lines. The following values can be formatted into it: client_ip, date_time, request_line, status_code, body_length, wall_seconds. The default is a good example of how to use it. :param url_length_limit: A maximum allowed length of the request url. If exceeded, 414 error is returned. :param debug: True if the server should send exception tracebacks to the clients on 500 errors. If False, the server will respond with empty bodies. + :param socket_timeout: Timeout for client connections' socket operations. Default None means wait forever. """ serv = Server(sock, sock.getsockname(), site, log, @@ -657,7 +661,9 @@ def server(sock, site, log_output=log_output, log_format=log_format, url_length_limit=url_length_limit, - debug=debug) + debug=debug, + socket_timeout=socket_timeout, + ) if server_event is not None: server_event.send(serv) if max_size is None: @@ -683,6 +689,7 @@ def server(sock, site, while True: try: client_socket = sock.accept() + client_socket[0].settimeout(serv.socket_timeout) if debug: serv.log.write("(%s) accepted %r\n" % ( serv.pid, client_socket[1])) diff --git a/tests/wsgi_test.py b/tests/wsgi_test.py index 3bbbd2f..0e10de7 100644 --- a/tests/wsgi_test.py +++ b/tests/wsgi_test.py @@ -1201,6 +1201,17 @@ class TestHttpd(_TestBase): self.assertTrue("BOOM" in runlog) self.assertFalse("Traceback" in runlog) + def test_server_socket_timeout(self): + self.spawn_server(socket_timeout=0.1) + sock = eventlet.connect(('localhost', self.port)) + sock.send('GET / HTTP/1.1\r\n') + eventlet.sleep(0.1) + try: + read_http(sock) + assert False, 'Expected ConnectionClosed exception' + except ConnectionClosed: + pass + def read_headers(sock): fd = sock.makefile()