Provide a way for all existing connections to be discarded

As I gather from various web searches, there's currently no way to manage the underlying TCP connections directly, since they're supposed to "just work" and be auto-recycled, etc. However, I have found one use case where this is not enough, and the sanest way to make it work would be to instruct `requests` to discard all open connections.

Here's the use case: I have a web API I've written that I'd like to test using `requests`. Each test case starts a new instance of the API server, runs the test code, then stops the server. Because the tests run in quick succession, there's a race condition between the time the server exits (and Linux cleans up the socket) and the time that `requests` sees that the connection was closed. So, when the second test runs and starts a new instance of the server, `requests` thinks it can reuse the previous connection, which then fails (throws an exception) because the remote socket no longer exists. This is not really the fault of `requests` (technically the behaviour is correct -- the connection _was_ closed, after all), but this lack of control on the client side of the connection in face of asynchronous cleanup makes it difficult to to these types of connection tests.

There's many workarounds I could use (currently I've inserted a sleep of 75ms between test runs, which works, as does using a different port for each test, or reusing the same instance of the server for all tests). But none of them are very elegant.

Note that this doesn't happen on Windows, for some reason, only Linux (Fedora 21).

Sample exception from the second test case (if I don't sleep):

```
Traceback (most recent call last):
  File "tests.py", line 52, in setUp
    requests.get(api, cookies=cookies)
  File "/usr/lib/python2.7/site-packages/requests-2.5.0-py2.7.egg/requests/api.py", line 65, in get
    return request('get', url, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests-2.5.0-py2.7.egg/requests/api.py", line 49, in request
    response = session.request(method=method, url=url, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests-2.5.0-py2.7.egg/requests/sessions.py", line 461, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/lib/python2.7/site-packages/requests-2.5.0-py2.7.egg/requests/sessions.py", line 573, in send
    r = adapter.send(request, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests-2.5.0-py2.7.egg/requests/adapters.py", line 415, in send
    raise ConnectionError(err, request=request)
ConnectionError: ('Connection aborted.', error(111, 'Connection refused'))
```


Hi there! Thanks for this detailed feature request.

Before we go too far I want to nail down exactly what's going on. Requests only re-uses connections at the scope of a single `Session` object. Given that you're calling `requests.get`, you should _not_ be seeing any connection re-use of any kind. We don't keep a single implicit session floating around. For that reason, I'm inclined to believe your problem is not actually caused by our connection re-use.

Is that analysis correct?


Oho! I thought it automatically reused connections even without a session object.

So yes, then, your analysis must be correct. I'm at a loss to explain what's happening, then.

I should note that when I run the tests on Windows with Fiddler capturing the traffic, it shows the first request of each test case taking an extra 500ms in the "TCP/IP Connect" stage, with subsequent ones (in that test case) taking 0ms. This to me suggests either a caching issue (e.g. DNS -- I had trouble at one point with localhost resolving to IPv6 first and causing a 1s delay on every new request in the same phase, but I "fixed" this by forcing localhost to resolve to 127.0.0.1) or connection reuse issue. Perhaps this is being done at a lower level than `requests` itself?


I suspect so.

Your DNS suggestion is a good explanation for the first request being delayed. Assuming you're running the test locally (that is, you're running both the server and test on localhost) that's a compelling explanation: TCP handshake should be <1ms on the loopback interface.

Connection Refused is the error code when the TCP SYN packet is rejected, meaning that no-one is listening on the socket. Is it possible your initial request occurs before the web server has actually started listening on the socket?


Oh -- I just realized where I put the sleep -- in between the process starting and the test starting. Obviously the race condition must be between the time the process starts and when the socket is actually bound, as you suggested. Thank you! I feel really stupid now :D

I still don't understand why it works without the delay for the first test, though (which is why I thought it was a lingering old connection ('Connection aborted' pointed in that direction), not a problem with the new one ('Connection refused' points in this one)), or why it always works on Windows. Alas, I guess that's just the nature of race conditions.

Sorry for wasting your time! My use case for this feature is completely invalid, it seems, so I'll withdraw the feature request.


It's not a waste of my time, I'm glad you asked. I hope you have success using requests!


Definitely! I remember the "good" old days of using urllib2... _shudder_ :-)