Automated merge with http://bitbucket.org/which_linden/eventlet/
This commit is contained in:
1
AUTHORS
1
AUTHORS
@@ -23,6 +23,7 @@ Linden Lab Contributors
|
|||||||
|
|
||||||
Thanks To
|
Thanks To
|
||||||
---------
|
---------
|
||||||
|
* gholt, wsgi patches for accepting a custom pool, and returning 400 if content-length is invalid
|
||||||
* Luke Tucker, bug report regarding wsgi + webob
|
* Luke Tucker, bug report regarding wsgi + webob
|
||||||
* Chuck Thier, reporting a bug in processes.py
|
* Chuck Thier, reporting a bug in processes.py
|
||||||
* Brantley Harris, reporting bug #4
|
* Brantley Harris, reporting bug #4
|
||||||
|
@@ -33,6 +33,8 @@ def inject(module_name, new_globals, *additional_modules):
|
|||||||
for name, mod in additional_modules:
|
for name, mod in additional_modules:
|
||||||
if saved[name] is not None:
|
if saved[name] is not None:
|
||||||
sys.modules[name] = saved[name]
|
sys.modules[name] = saved[name]
|
||||||
|
else:
|
||||||
|
del sys.modules[name]
|
||||||
|
|
||||||
return module
|
return module
|
||||||
|
|
||||||
|
@@ -167,6 +167,17 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||||||
if not self.parse_request():
|
if not self.parse_request():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
content_length = self.headers.getheader('content-length')
|
||||||
|
if content_length:
|
||||||
|
try:
|
||||||
|
int(content_length)
|
||||||
|
except ValueError:
|
||||||
|
self.wfile.write(
|
||||||
|
"HTTP/1.0 400 Bad Request\r\n"
|
||||||
|
"Connection: close\r\nContent-length: 0\r\n\r\n")
|
||||||
|
self.close_connection = 1
|
||||||
|
return
|
||||||
|
|
||||||
self.environ = self.get_environ()
|
self.environ = self.get_environ()
|
||||||
self.application = self.server.app
|
self.application = self.server.app
|
||||||
try:
|
try:
|
||||||
@@ -423,7 +434,8 @@ def server(sock, site,
|
|||||||
protocol=HttpProtocol,
|
protocol=HttpProtocol,
|
||||||
server_event=None,
|
server_event=None,
|
||||||
minimum_chunk_size=None,
|
minimum_chunk_size=None,
|
||||||
log_x_forwarded_for=True):
|
log_x_forwarded_for=True,
|
||||||
|
custom_pool=None):
|
||||||
""" Start up a `WSGI <http://wsgi.org/wsgi/>`_ server handling requests from the supplied server
|
""" Start up a `WSGI <http://wsgi.org/wsgi/>`_ server handling requests from the supplied server
|
||||||
socket. This function loops forever.
|
socket. This function loops forever.
|
||||||
|
|
||||||
@@ -449,6 +461,9 @@ def server(sock, site,
|
|||||||
server_event.send(serv)
|
server_event.send(serv)
|
||||||
if max_size is None:
|
if max_size is None:
|
||||||
max_size = DEFAULT_MAX_SIMULTANEOUS_REQUESTS
|
max_size = DEFAULT_MAX_SIMULTANEOUS_REQUESTS
|
||||||
|
if custom_pool is not None:
|
||||||
|
pool = custom_pool
|
||||||
|
else:
|
||||||
pool = Pool(max_size=max_size)
|
pool = Pool(max_size=max_size)
|
||||||
try:
|
try:
|
||||||
host, port = sock.getsockname()
|
host, port = sock.getsockname()
|
||||||
|
72
tests/patcher_test.py
Normal file
72
tests/patcher_test.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from tests import LimitedTestCase
|
||||||
|
|
||||||
|
base_module_contents = """
|
||||||
|
import socket
|
||||||
|
import urllib
|
||||||
|
print "base", socket, urllib
|
||||||
|
"""
|
||||||
|
|
||||||
|
patching_module_contents = """
|
||||||
|
from eventlet.green import socket
|
||||||
|
from eventlet.green import urllib
|
||||||
|
from eventlet import patcher
|
||||||
|
print 'patcher', socket, urllib
|
||||||
|
patcher.inject('%s', globals(), ('socket', socket), ('urllib', urllib))
|
||||||
|
del patcher
|
||||||
|
"""
|
||||||
|
|
||||||
|
import_module_contents = """
|
||||||
|
import %(mod)s
|
||||||
|
import httplib
|
||||||
|
print "importing", %(mod)s, httplib, %(mod)s.socket, %(mod)s.urllib
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Patcher(LimitedTestCase):
|
||||||
|
TEST_TIMEOUT=3 # starting processes is time-consuming
|
||||||
|
def setUp(self):
|
||||||
|
self._saved_syspath = sys.path
|
||||||
|
self.tempfiles = []
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
sys.path = self._saved_syspath
|
||||||
|
for tf in self.tempfiles:
|
||||||
|
os.remove(tf)
|
||||||
|
|
||||||
|
def write_to_tempfile(self, contents):
|
||||||
|
fn, filename = tempfile.mkstemp('_patcher_test.py')
|
||||||
|
fd = os.fdopen(fn, 'w')
|
||||||
|
fd.write(contents)
|
||||||
|
fd.close()
|
||||||
|
self.tempfiles.append(filename)
|
||||||
|
return os.path.dirname(filename), os.path.basename(filename)
|
||||||
|
|
||||||
|
def test_patch_a_module(self):
|
||||||
|
base = self.write_to_tempfile(base_module_contents)
|
||||||
|
base_modname = os.path.splitext(base[1])[0]
|
||||||
|
patching = self.write_to_tempfile(patching_module_contents % base_modname)
|
||||||
|
patching_modname = os.path.splitext(patching[1])[0]
|
||||||
|
importing = self.write_to_tempfile(
|
||||||
|
import_module_contents % dict(mod=patching_modname))
|
||||||
|
|
||||||
|
python_path = os.pathsep.join(sys.path)
|
||||||
|
python_path += os.pathsep.join((base[0], patching[0], importing[0]))
|
||||||
|
new_env = os.environ.copy()
|
||||||
|
new_env['PYTHONPATH'] = python_path
|
||||||
|
p = subprocess.Popen([sys.executable,
|
||||||
|
os.path.join(importing[0], importing[1])],
|
||||||
|
stdout=subprocess.PIPE, env=new_env)
|
||||||
|
output = p.communicate()
|
||||||
|
lines = output[0].split("\n")
|
||||||
|
self.assert_(lines[0].startswith('patcher'))
|
||||||
|
self.assert_(lines[1].startswith('base'))
|
||||||
|
self.assert_(lines[2].startswith('importing'))
|
||||||
|
self.assert_('eventlet.green.socket' in lines[1])
|
||||||
|
self.assert_('eventlet.green.urllib' in lines[1])
|
||||||
|
self.assert_('eventlet.green.socket' in lines[2])
|
||||||
|
self.assert_('eventlet.green.urllib' in lines[2])
|
||||||
|
self.assert_('eventlet.green.httplib' not in lines[2])
|
@@ -491,6 +491,44 @@ class TestHttpd(LimitedTestCase):
|
|||||||
'\r\n\r\n')
|
'\r\n\r\n')
|
||||||
self.assert_('200 OK' in fd.read())
|
self.assert_('200 OK' in fd.read())
|
||||||
|
|
||||||
|
def test_022_custom_pool(self):
|
||||||
|
# just test that it accepts the parameter for now
|
||||||
|
# TODO: test that it uses the pool and that you can waitall() to
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# this stuff is copied from test_001_server, could be better factored
|
||||||
|
sock = api.connect_tcp(
|
||||||
|
('localhost', self.port))
|
||||||
|
fd = sock.makeGreenFile()
|
||||||
|
fd.write('GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
|
||||||
|
result = fd.read()
|
||||||
|
fd.close()
|
||||||
|
self.assert_(result.startswith('HTTP'), result)
|
||||||
|
self.assert_(result.endswith('hello world'))
|
||||||
|
|
||||||
|
def test_023_bad_content_length(self):
|
||||||
|
sock = api.connect_tcp(
|
||||||
|
('localhost', self.port))
|
||||||
|
fd = sock.makeGreenFile()
|
||||||
|
fd.write('GET / HTTP/1.0\r\nHost: localhost\r\nContent-length: argh\r\n\r\n')
|
||||||
|
result = fd.read()
|
||||||
|
fd.close()
|
||||||
|
self.assert_(result.startswith('HTTP'), result)
|
||||||
|
self.assert_('400 Bad Request' in result)
|
||||||
|
self.assert_('500' not in result)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
Reference in New Issue
Block a user