diff --git a/AUTHORS b/AUTHORS
index efe4a6f..8a210e9 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -23,6 +23,7 @@ Linden Lab Contributors
Thanks To
---------
+* Michael Barton, 100-continue patch, content-length bugfixes for wsgi
* gholt, wsgi patches for accepting a custom pool, and returning 400 if content-length is invalid
* Luke Tucker, bug report regarding wsgi + webob
* Chuck Thier, reporting a bug in processes.py
diff --git a/doc/real_index.html b/doc/real_index.html
index c4b98a5..f3b0bd7 100644
--- a/doc/real_index.html
+++ b/doc/real_index.html
@@ -22,9 +22,7 @@
Eventlet is a networking library written in Python. It achieves high scalability by using non-blocking io while at the same time retaining high programmer usability by using coroutines to make the non-blocking io operations appear blocking at the source code level.
-Documentation
-
-API Documentation
+
Installation
@@ -47,10 +45,16 @@ easy_install eventlet
Development
-"root" repository
+trunk repository
We use Mercurial for our source control, hosted by BitBucket. It's easy to branch off the main repository and contribute patches, tests, and documentation back upstream.
+Bugs
+
+Bug Report Form
+
+No registration is required. Please be sure to report bugs as effectively as possible, to ensure that we understand and act on them quickly.
+
Web Crawler Example
This is a simple web “crawler” that fetches a bunch of urls using a coroutine pool. It has as much concurrency (i.e. pages being fetched simultaneously) as coroutines in the pool.
@@ -78,9 +82,13 @@ easy_install eventlet
for waiter in waiters:
waiter.wait()
+
+Stats
+
+
@@ -92,6 +100,7 @@ easy_install eventlet
diff --git a/eventlet/db_pool.py b/eventlet/db_pool.py
index 1b1f731..6be0a1c 100644
--- a/eventlet/db_pool.py
+++ b/eventlet/db_pool.py
@@ -297,14 +297,14 @@ class GenericConnectionWrapper(object):
def character_set_name(self,*args, **kwargs): return self._base.character_set_name(*args, **kwargs)
def close(self,*args, **kwargs): return self._base.close(*args, **kwargs)
def commit(self,*args, **kwargs): return self._base.commit(*args, **kwargs)
- def cursor(self, cursorclass=None, **kwargs): return self._base.cursor(cursorclass, **kwargs)
+ def cursor(self, *args, **kwargs): return self._base.cursor(*args, **kwargs)
def dump_debug_info(self,*args, **kwargs): return self._base.dump_debug_info(*args, **kwargs)
def errno(self,*args, **kwargs): return self._base.errno(*args, **kwargs)
def error(self,*args, **kwargs): return self._base.error(*args, **kwargs)
- def errorhandler(self, conn, curs, errcls, errval): return self._base.errorhandler(conn, curs, errcls, errval)
- def literal(self, o): return self._base.literal(o)
- def set_character_set(self, charset): return self._base.set_character_set(charset)
- def set_sql_mode(self, sql_mode): return self._base.set_sql_mode(sql_mode)
+ def errorhandler(self, *args, **kwargs): return self._base.errorhandler(*args, **kwargs)
+ def literal(self, *args, **kwargs): return self._base.literal(*args, **kwargs)
+ def set_character_set(self, *args, **kwargs): return self._base.set_character_set(*args, **kwargs)
+ def set_sql_mode(self, *args, **kwargs): return self._base.set_sql_mode(*args, **kwargs)
def show_warnings(self): return self._base.show_warnings()
def warning_count(self): return self._base.warning_count()
def ping(self,*args, **kwargs): return self._base.ping(*args, **kwargs)
@@ -315,7 +315,7 @@ class GenericConnectionWrapper(object):
def server_capabilities(self,*args, **kwargs): return self._base.server_capabilities(*args, **kwargs)
def shutdown(self,*args, **kwargs): return self._base.shutdown(*args, **kwargs)
def sqlstate(self,*args, **kwargs): return self._base.sqlstate(*args, **kwargs)
- def stat(self,*args, **kwargs): return self._base.stat(*args, **kwargs)
+ def stat(self, *args, **kwargs): return self._base.stat(*args, **kwargs)
def store_result(self,*args, **kwargs): return self._base.store_result(*args, **kwargs)
def string_literal(self,*args, **kwargs): return self._base.string_literal(*args, **kwargs)
def thread_id(self,*args, **kwargs): return self._base.thread_id(*args, **kwargs)
diff --git a/eventlet/wsgi.py b/eventlet/wsgi.py
index b6db8da..ef2c62f 100644
--- a/eventlet/wsgi.py
+++ b/eventlet/wsgi.py
@@ -297,8 +297,10 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
if hasattr(result, 'close'):
result.close()
if self.environ['eventlet.input'].position < self.environ.get('CONTENT_LENGTH', 0):
- ## Read and discard body
- self.environ['eventlet.input'].read()
+ ## Read and discard body if there was no pending 100-continue
+ if not self.environ['eventlet.input'].wfile:
+ while self.environ['eventlet.input'].read(MINIMUM_CHUNK_SIZE):
+ pass
finish = time.time()
self.server.log_message('%s - - [%s] "%s" %s %s %.6f' % (
diff --git a/tests/wsgi_test.py b/tests/wsgi_test.py
index 024df3a..cde6ee1 100644
--- a/tests/wsgi_test.py
+++ b/tests/wsgi_test.py
@@ -585,6 +585,30 @@ class TestHttpd(LimitedTestCase):
self.assert_('400 Bad Request' in result)
self.assert_('500' not in result)
+ def test_024_expect_100_continue(self):
+ def wsgi_app(environ, start_response):
+ if int(environ['CONTENT_LENGTH']) > 1024:
+ start_response('417 Expectation Failed', [('Content-Length', '7')])
+ return ['failure']
+ else:
+ text = environ['wsgi.input'].read()
+ start_response('200 OK', [('Content-Length', str(len(text)))])
+ return [text]
+ self.site.application = wsgi_app
+ sock = api.connect_tcp(('localhost', self.port))
+ fd = sock.makeGreenFile()
+ fd.write('PUT / HTTP/1.1\r\nHost: localhost\r\nContent-length: 1025\r\nExpect: 100-continue\r\n\r\n')
+ result = fd.readuntil('\r\n\r\n')
+ self.assert_(result.startswith('HTTP/1.1 417 Expectation Failed'))
+ self.assertEquals(fd.read(7), 'failure')
+ fd.write('PUT / HTTP/1.1\r\nHost: localhost\r\nContent-length: 7\r\nExpect: 100-continue\r\n\r\ntesting')
+ result = fd.readuntil('\r\n\r\n')
+ self.assert_(result.startswith('HTTP/1.1 100 Continue'))
+ result = fd.readuntil('\r\n\r\n')
+ self.assert_(result.startswith('HTTP/1.1 200 OK'))
+ self.assertEquals(fd.read(7), 'testing')
+ fd.close()
+
if __name__ == '__main__':
main()