wsgi: Allow minimum_chunk_size to be overriden on a per request basis
The application can set environ['eventlet.minimum_write_chunk_size'] which will override the minimum_chunk_size set on server initialization for a single request. https://bitbucket.org/eventlet/eventlet/pull-request/37/allow-minimum_chunk_size-to-be-overriden
This commit is contained in:

committed by
Sergey Shepelev

parent
25bc2c402d
commit
bc796c4f65
@@ -397,10 +397,12 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
towrite = []
|
||||
towrite_size = 0
|
||||
just_written_size = 0
|
||||
minimum_write_chunk_size = int(self.environ.get(
|
||||
'eventlet.minimum_write_chunk_size', self.minimum_chunk_size))
|
||||
for data in result:
|
||||
towrite.append(data)
|
||||
towrite_size += len(data)
|
||||
if towrite_size >= self.minimum_chunk_size:
|
||||
if towrite_size >= minimum_write_chunk_size:
|
||||
write(''.join(towrite))
|
||||
towrite = []
|
||||
just_written_size = towrite_size
|
||||
@@ -640,7 +642,7 @@ def server(sock, site,
|
||||
:param max_http_version: Set to "HTTP/1.0" to make the server pretend it only supports HTTP 1.0. This can help with applications or clients that don't behave properly using HTTP 1.1.
|
||||
: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 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. This can be overridden on a per request basis by setting environ['eventlet.minimum_write_chunk_size'].
|
||||
: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 GreenPool instance which is used to spawn client green threads. If this is supplied, max_size is ignored.
|
||||
:param keepalive: If set to False, disables keepalives on the server; all connections will be closed after serving one request.
|
||||
|
@@ -1301,6 +1301,24 @@ class TestChunkedInput(_TestBase):
|
||||
elif pi=="/ping":
|
||||
input.read()
|
||||
response.append("pong")
|
||||
elif pi.startswith("/yield_spaces"):
|
||||
if pi.endswith('override_min'):
|
||||
env['eventlet.minimum_write_chunk_size'] = 1
|
||||
self.yield_next_space = False
|
||||
|
||||
def response_iter():
|
||||
yield ' '
|
||||
num_sleeps = 0
|
||||
while not self.yield_next_space and num_sleeps < 200:
|
||||
eventlet.sleep(.01)
|
||||
num_sleeps += 1
|
||||
|
||||
yield ' '
|
||||
|
||||
start_response('200 OK',
|
||||
[('Content-Type', 'text/plain'),
|
||||
('Content-Length', '2')])
|
||||
return response_iter()
|
||||
else:
|
||||
raise RuntimeError("bad path")
|
||||
|
||||
@@ -1377,6 +1395,50 @@ class TestChunkedInput(_TestBase):
|
||||
fd.sendall(req)
|
||||
self.assertEquals(read_http(fd)[-1], 'this is chunked\nline 2\nline3')
|
||||
|
||||
def test_chunked_readline_wsgi_override_minimum_chunk_size(self):
|
||||
|
||||
fd = self.connect()
|
||||
fd.sendall("POST /yield_spaces/override_min HTTP/1.1\r\nContent-Length: 0\r\n\r\n")
|
||||
|
||||
resp_so_far = ''
|
||||
with eventlet.Timeout(.1):
|
||||
while True:
|
||||
one_byte = fd.recv(1)
|
||||
resp_so_far += one_byte
|
||||
if resp_so_far.endswith('\r\n\r\n'):
|
||||
break
|
||||
self.assertEquals(fd.recv(1), ' ')
|
||||
try:
|
||||
with eventlet.Timeout(.1):
|
||||
fd.recv(1)
|
||||
except eventlet.Timeout:
|
||||
pass
|
||||
else:
|
||||
self.assert_(False)
|
||||
self.yield_next_space = True
|
||||
|
||||
with eventlet.Timeout(.1):
|
||||
self.assertEquals(fd.recv(1), ' ')
|
||||
|
||||
def test_chunked_readline_wsgi_not_override_minimum_chunk_size(self):
|
||||
|
||||
fd = self.connect()
|
||||
fd.sendall("POST /yield_spaces HTTP/1.1\r\nContent-Length: 0\r\n\r\n")
|
||||
|
||||
resp_so_far = ''
|
||||
try:
|
||||
with eventlet.Timeout(.1):
|
||||
while True:
|
||||
one_byte = fd.recv(1)
|
||||
resp_so_far += one_byte
|
||||
if resp_so_far.endswith('\r\n\r\n'):
|
||||
break
|
||||
self.assertEquals(fd.recv(1), ' ')
|
||||
except eventlet.Timeout:
|
||||
pass
|
||||
else:
|
||||
self.assert_(False)
|
||||
|
||||
def test_close_before_finished(self):
|
||||
import signal
|
||||
|
||||
|
Reference in New Issue
Block a user