gabrielfalcao / HTTPretty

Intercept HTTP requests at the Python socket level. Fakes the whole socket module
https://httpretty.readthedocs.org
MIT License
2.11k stars 276 forks source link

ConnectionError when making multiple requests using a session on Windows #442

Open R-Broadley opened 3 years ago

R-Broadley commented 3 years ago

When making multiple requests using a requests.Session on Windows, I get the following error:

requests.exceptions.ConnectionError: ('Connection aborted.', OSError(10038, 'An operation was attempted on something that is not a socket', None, 10038, None)) 

The issue can be reproduced as follows (Tested on Windows 10 21H1, Python 3.8.5, httpretty 1.1.4, requests 2.26.0, urllib3 1.26.7):

import httpretty
import requests

BASE_URI = "http://192.0.2.1"

def callback(*_):
    return 200, {}, "test"

with httpretty.enabled(allow_net_connect=False):
    # Register 2 URIs.
    httpretty.register_uri(
        httpretty.POST,
        f"{BASE_URI}/api/1",
        body=callback,
    )
    httpretty.register_uri(
        httpretty.GET,
        f"{BASE_URI}/api/2",
        body="text",
    )
    # Create session and make two requests (first request must go through callback).
    session = requests.Session()
    session.post(
        f"{BASE_URI}/api/1",
    )
    try:
        session.get(f"{BASE_URI}/api/2")
    except OSError as e:
        print("Fail - got OS Error on second request using session.")
        raise e

The issue is caused by a call to urllib3.util.wait.select_wait_for_socket (Link to function in urllib3). This function makes a call to select.select which is an interface to the OS's select system call. The problem is that on Windows select only accepts file descriptors which are a socket (on Unix any file is accepted), however the HTTPretty FakeSockFile is a tempfile.TemporaryFile.

It doesn't look difficult to patch urllib3.util.wait.select_wait_for_socket in core.apply_patch_socket with a mock which always returns True - the fake socket should always be ready.

@gabrielfalcao As far as I can see the unit tests get run on Ubuntu, since this is a Windows issue I'm not sure how best to approach adding a unit test for this?

R-Broadley commented 3 years ago

This could be related to Issue #381