gabrielfalcao / HTTPretty

Intercept HTTP requests at the Python socket level. Fakes the whole socket module

Home Page:https://httpretty.readthedocs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Making requests to non-stadard port throws TimeoutError

ipetepete opened this issue · comments

Python: 3.8.0
httpretty: 0.9.7

What I tried:

import httpretty
import requests
httpretty.register_uri(httpretty.GET, 'http://fakeuri.com:8080', body='{"hello":"world"}')
req = requests.get('http://fakeuri.com:8080')

What I expected:

req.status = 200
req.json() ={"hello":"world"}

What I got:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 600, in urlopen
    chunked=chunked)
  File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 354, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/local/lib/python3.6/http/client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/local/lib/python3.6/http/client.py", line 1285, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/local/lib/python3.6/http/client.py", line 1234, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/local/lib/python3.6/http/client.py", line 1026, in _send_output
    self.send(msg)
  File "/usr/local/lib/python3.6/http/client.py", line 986, in send
    self.sock.sendall(data)
  File "/usr/local/lib/python3.6/site-packages/httpretty/core.py", line 554, in sendall
    self.real_sendall(data)
  File "/usr/local/lib/python3.6/site-packages/httpretty/core.py", line 474, in real_sendall
    sock.connect(self._address)
TimeoutError: [Errno 110] Connection timed out
commented

Problem is not in the port, it is in the registered uri (but, unfortunately, I didn't find it explicitly stated in the documentation).
You must add a trailing / to a registering uri: http://fakeuri.com:8080/.
Also, you forgot to call enable().
Here is a working example:

    import httpretty
    import requests

    httpretty.enable()
    httpretty.register_uri(httpretty.GET, 'http://fakeuri.com:8080/', body='{"hello":"world"}')
    req = requests.get('http://fakeuri.com:8080', timeout=1)
    assert req.status_code == 200
    assert req.json() == {"hello": "world"}

Good catch on the trailing / ! Thanks for the help. I'll close this and make a pull request updating the documentation.

commented

In fact, there is a workaround in register_uri for a missing trailing /:

if uri_is_string and re.search(r'^\w+://[^/]+[.]\w{2,}$', uri):

But the regex doesn't work for a uri with a port (so, this issue could be considered as a bug).
Maybe it would be better to improve this regex, rather than updating the documentation.
Unfortunately, I saw this line only after I'd posted an answer.

I thought about that after I made the pull request. Feels wrong to have a warning/caveat to usage in that manner.

I have tried the following regex and it works:
re.search(r'^\w+://[^/]+[.]\w{2,}(:[0-9]+)?$', uri)

But unfortunately I can't get the tests to run using virtualenv and I get errors in pipenv, probably because my python version is 3.8.7...idk, but I can't chase that down right now. I'll submit a pull request with the new regex once I have time to fiddle with running the tests.

@ipetepete and @azurkin I'll soon open a PR using your snippets as base.

Thanks for taking time to report the issues so thoroughly :)