Merge
This commit is contained in:
1
AUTHORS
1
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
|
||||
|
@@ -22,9 +22,7 @@
|
||||
|
||||
<p>Eventlet is a networking library written in Python. It achieves high scalability by using <a class="reference external" href="http://en.wikipedia.org/wiki/Asynchronous_I/O#Select.28.2Fpoll.29_loops">non-blocking io</a> while at the same time retaining high programmer usability by using <a class="reference external" href="http://en.wikipedia.org/wiki/Coroutine">coroutines</a> to make the non-blocking io operations appear blocking at the source code level.</p>
|
||||
|
||||
<h3>Documentation</h3>
|
||||
|
||||
<a href="doc/">API Documentation</a>
|
||||
<h3><a href="doc/">API Documentation</a></h3>
|
||||
|
||||
<h3>Installation</h3>
|
||||
|
||||
@@ -47,10 +45,16 @@ easy_install eventlet
|
||||
|
||||
<h3>Development</h3>
|
||||
|
||||
<p><a href="http://bitbucket.org/which_linden/eventlet/">"root" repository</a></p>
|
||||
<p><a href="http://bitbucket.org/which_linden/eventlet/">trunk repository</a></p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h4>Bugs</h4>
|
||||
|
||||
<p><a href="http://bitbucket.org/which_linden/eventlet/issues/new/">Bug Report Form</a></p>
|
||||
|
||||
<p>No registration is required. Please be sure to report bugs <a href="http://www.chiark.greenend.org.uk/~sgtatham/bugs.html">as effectively as possible</a>, to ensure that we understand and act on them quickly.</p>
|
||||
|
||||
<div class="section" id="web-crawler-example">
|
||||
<h2>Web Crawler Example<a class="headerlink" href="#web-crawler-example" title="Permalink to this headline">¶</a></h2>
|
||||
<p>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.</p>
|
||||
@@ -78,9 +82,13 @@ easy_install eventlet
|
||||
<span class="k">for</span> <span class="n">waiter</span> <span class="ow">in</span> <span class="n">waiters</span><span class="p">:</span>
|
||||
<span class="n">waiter</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
|
||||
<h3>Stats</h3>
|
||||
<script type="text/javascript" src="http://www.ohloh.net/p/480234/widgets/project_basic_stats.js"></script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section" id="contents">
|
||||
</div>
|
||||
</div>
|
||||
@@ -92,6 +100,7 @@ easy_install eventlet
|
||||
<ul>
|
||||
<li><a class="reference external" href="doc/">Documentation</a></li>
|
||||
<li><a class="reference external" href="https://lists.secondlife.com/pipermail/eventletdev/">Mailing list archives</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -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)
|
||||
|
@@ -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' % (
|
||||
|
@@ -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()
|
||||
|
Reference in New Issue
Block a user