shazow/urllib3 — pull request #17 by poupas (2011-12-05 00:02:07+00:00)
Title: Ensure that the user-specified timeout is set before making a request

Hi,

urllib3 apparently does not honor the timeout value when establishing a new connection.

In the code, one can see that the timeout value is being set on the socket, albeit only after the connection attempt.

conn.request(method, url, **httplib_request_kw)
conn.sock.settimeout(timeout)

I believe this partly defeats the purpose of the timeout parameter.

Here's a small script that illustrates this:

import urllib3
conn = urllib3.connection_from_url('http://host.that.times.out', timeout=1.0)
r1 = conn.request('GET', '/')

Results

Without the change:
time python urllib3_timeout.py
Traceback (most recent call last):
File "urllib3_timeout.py", line 4, in
r1 = conn.request('GET', '/')
File "/usr/local/lib/python2.6/dist-packages/urllib3-1.0.2-py2.6.egg/urllib3/request.py", line 65, in request
**urlopen_kw)
File "/usr/local/lib/python2.6/dist-packages/urllib3-1.0.2-py2.6.egg/urllib3/request.py", line 78, in request_encode_url
return self.urlopen(method, url, **urlopen_kw)
File "/usr/local/lib/python2.6/dist-packages/urllib3-1.0.2-py2.6.egg/urllib3/connectionpool.py", line 361, in urlopen
redirect, assert_same_host) # Try again
File "/usr/local/lib/python2.6/dist-packages/urllib3-1.0.2-py2.6.egg/urllib3/connectionpool.py", line 361, in urlopen
redirect, assert_same_host) # Try again
File "/usr/local/lib/python2.6/dist-packages/urllib3-1.0.2-py2.6.egg/urllib3/connectionpool.py", line 361, in urlopen
redirect, assert_same_host) # Try again
File "/usr/local/lib/python2.6/dist-packages/urllib3-1.0.2-py2.6.egg/urllib3/connectionpool.py", line 361, in urlopen
redirect, assert_same_host) # Try again
File "/usr/local/lib/python2.6/dist-packages/urllib3-1.0.2-py2.6.egg/urllib3/connectionpool.py", line 296, in urlopen
raise MaxRetryError("Max retries exceeded for url: %s" % url)
urllib3.exceptions.MaxRetryError: Max retries exceeded for url: /

real	1m24.056s
user	0m0.044s
sys	0m0.016s

With the change:
time python urllib3_timeout.py
Traceback (most recent call last):
File "urllib3_timeout.py", line 4, in
r1 = conn.request('GET', '/')
File "/usr/local/lib/python2.6/dist-packages/urllib3-1.0.2-py2.6.egg/urllib3/request.py", line 65, in request
**urlopen_kw)
File "/usr/local/lib/python2.6/dist-packages/urllib3-1.0.2-py2.6.egg/urllib3/request.py", line 78, in request_encode_url
return self.urlopen(method, url, **urlopen_kw)
File "/usr/local/lib/python2.6/dist-packages/urllib3-1.0.2-py2.6.egg/urllib3/connectionpool.py", line 344, in urlopen
self.timeout)
urllib3.exceptions.TimeoutError: Request timed out after 1.000000 seconds

real	0m1.040s
user	0m0.020s
sys	0m0.020s

Hope you find the patch useful.

Thank you for your work.