A little wsgi_test refactoring, added log_format argument to wsgi.server.

This commit is contained in:
Ryan Williams
2010-01-08 17:44:24 -08:00
parent 7003ded07c
commit adc1d7bb8a
2 changed files with 56 additions and 46 deletions

View File

@@ -15,6 +15,7 @@ DEFAULT_MAX_SIMULTANEOUS_REQUESTS = 1024
DEFAULT_MAX_HTTP_VERSION = 'HTTP/1.1'
MAX_REQUEST_LINE = 8192
MINIMUM_CHUNK_SIZE = 4096
DEFAULT_LOG_FORMAT='%(client_ip)s - - [%(date_time)s] "%(request_line)s" %(status_code)s %(body_length)s %(wall_seconds).6f'
__all__ = ['server', 'format_date_time']
@@ -303,13 +304,13 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
pass
finish = time.time()
self.server.log_message('%s - - [%s] "%s" %s %s %.6f' % (
self.get_client_ip(),
self.log_date_time_string(),
self.requestline,
status_code[0],
length[0],
finish - start))
self.server.log_message(self.server.log_format % dict(
client_ip=self.get_client_ip(),
date_time=self.log_date_time_string(),
request_line=self.requestline,
status_code=status_code[0],
body_length=length[0],
wall_seconds=finish - start))
def get_client_ip(self):
client_ip = self.client_address[0]
@@ -388,8 +389,9 @@ class Server(BaseHTTPServer.HTTPServer):
max_http_version=None,
protocol=HttpProtocol,
minimum_chunk_size=None,
log_x_forwarded_for=True):
log_x_forwarded_for=True,
log_format=DEFAULT_LOG_FORMAT):
self.outstanding_requests = 0
self.socket = socket
self.address = address
@@ -405,6 +407,7 @@ class Server(BaseHTTPServer.HTTPServer):
if minimum_chunk_size is not None:
protocol.minimum_chunk_size = minimum_chunk_size
self.log_x_forwarded_for = log_x_forwarded_for
self.log_format = log_format
def get_environ(self):
socket = self.socket
@@ -437,7 +440,8 @@ def server(sock, site,
server_event=None,
minimum_chunk_size=None,
log_x_forwarded_for=True,
custom_pool=None):
custom_pool=None,
log_format=DEFAULT_LOG_FORMAT):
""" Start up a `WSGI <http://wsgi.org/wsgi/>`_ server handling requests from the supplied server
socket. This function loops forever.
@@ -449,17 +453,18 @@ def server(sock, site,
:param protocol: Protocol class. Deprecated.
:param server_event: Used to collect the Server object. Deprecated.
:param minimum_chunk_size: Minimum size in bytes for http chunks. This can be used to improve performance of applications which yield many small strings, though using it technically violates the WSGI spec.
:param log_x_forwarded_for: If True (the default), logs the contents of the x-forwarded-for header in addition to the actual client ip address.
:param log_x_forwarded_for: If True (the default), logs the contents of the x-forwarded-for header in addition to the actual client ip address in the 'client_ip' field of the log line.
:param custom_pool: A custom Pool instance which is used to spawn client green threads. If this is supplied, max_size is ignored.
:param log_formar: 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. Look at DEFAULT_LOG_FORMAT for an example of how to use this.
"""
serv = Server(sock, sock.getsockname(),
site, log,
environ=None,
max_http_version=max_http_version,
protocol=protocol,
minimum_chunk_size=minimum_chunk_size,
log_x_forwarded_for=log_x_forwarded_for)
log_x_forwarded_for=log_x_forwarded_for,
log_format=log_format)
if server_event is not None:
server_event.send(serv)
if max_size is None:

View File

@@ -124,20 +124,36 @@ class TestHttpd(LimitedTestCase):
super(TestHttpd, self).setUp()
self.logfile = StringIO()
self.site = Site()
listener = api.tcp_listener(('localhost', 0))
self.port = listener.getsockname()[1]
self.killer = api.spawn(
wsgi.server,
listener,
self.site,
max_size=128,
log=self.logfile)
self.killer = None
self.spawn_server()
def tearDown(self):
super(TestHttpd, self).tearDown()
api.kill(self.killer)
api.sleep(0)
def spawn_server(self, **kwargs):
"""Spawns a new wsgi server with the given arguments.
Sets self.port to the port of the server, and self.killer is the greenlet
running it.
Kills any previously-running server."""
if self.killer:
api.kill(self.killer)
new_kwargs = dict(max_size=128,
log=self.logfile,
site=self.site)
new_kwargs.update(kwargs)
if 'sock' not in new_kwargs:
new_kwargs['sock'] = api.tcp_listener(('localhost', 0))
self.port = new_kwargs['sock'].getsockname()[1]
self.killer = api.spawn(
wsgi.server,
**new_kwargs)
def test_001_server(self):
sock = api.connect_tcp(
('localhost', self.port))
@@ -317,10 +333,9 @@ class TestHttpd(LimitedTestCase):
private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
server_sock = api.ssl_listener(('localhost', 0), certificate_file, private_key_file)
api.spawn(wsgi.server, server_sock, wsgi_app, log=StringIO())
self.spawn_server(sock=server_sock, site=wsgi_app)
sock = api.connect_tcp(('localhost', server_sock.getsockname()[1]))
sock = api.connect_tcp(('localhost', self.port))
sock = util.wrap_ssl(sock)
sock.write('POST /foo HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\nContent-length:3\r\n\r\nabc')
result = sock.read(8192)
@@ -334,7 +349,7 @@ class TestHttpd(LimitedTestCase):
certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
server_sock = api.ssl_listener(('localhost', 0), certificate_file, private_key_file)
api.spawn(wsgi.server, server_sock, wsgi_app, log=StringIO())
self.spawn_server(sock=server_sock, site=wsgi_app)
sock = api.connect_tcp(('localhost', server_sock.getsockname()[1]))
sock = util.wrap_ssl(sock)
@@ -505,16 +520,7 @@ class TestHttpd(LimitedTestCase):
# turning off the option should work too
self.logfile = StringIO()
api.kill(self.killer)
listener = api.tcp_listener(('localhost', 0))
self.port = listener.getsockname()[1]
self.killer = api.spawn(
wsgi.server,
listener,
self.site,
max_size=128,
log=self.logfile,
log_x_forwarded_for=False)
self.spawn_server(log_x_forwarded_for=False)
sock = api.connect_tcp(('localhost', self.port))
sock.sendall('GET / HTTP/1.1\r\nHost: localhost\r\nX-Forwarded-For: 1.2.3.4, 5.6.7.8\r\n\r\n')
@@ -551,16 +557,7 @@ class TestHttpd(LimitedTestCase):
# ensure that all clients finished
from eventlet import pool
p = pool.Pool(max_size=5)
api.kill(self.killer)
listener = api.tcp_listener(('localhost', 0))
self.port = listener.getsockname()[1]
self.killer = api.spawn(
wsgi.server,
listener,
self.site,
max_size=128,
log=self.logfile,
custom_pool=p)
self.spawn_server(custom_pool=p)
# this stuff is copied from test_001_server, could be better factored
sock = api.connect_tcp(
@@ -623,6 +620,14 @@ class TestHttpd(LimitedTestCase):
self.assertEquals(fd.read(7), 'testing')
fd.close()
def test_025_log_format(self):
self.spawn_server(log_format="HI %(request_line)s HI")
sock = api.connect_tcp(('localhost', self.port))
sock.sendall('GET /yo! HTTP/1.1\r\nHost: localhost\r\n\r\n')
sock.recv(1024)
sock.close()
self.assert_('\nHI GET /yo! HTTP/1.1 HI\n' in self.logfile.getvalue(), self.logfile.getvalue())
if __name__ == '__main__':
main()