mindflayer / python-mocket

a socket mock framework - for all kinds of socket animals, web-clients included
BSD 3-Clause "New" or "Revised" License
280 stars 42 forks source link

Mocket fails to mock HTTPS after upgrading `urllib3` to `1.26.5` #151

Closed ghost closed 3 years ago

ghost commented 3 years ago

Describe the bug Mocket on version 3.9.41 is not working well with HTTPS URLs.

To Reproduce Steps to reproduce the behavior: it's failing your test tests/main/test_httpretty.py::test_rotating_responses_with_requests.

FAILED tests/main/test_httpretty.py::test_rotating_responses_with_requests - requests.exceptions.SSLError: HTTPSConnectionPool(host='api.yahoo.com', port=443): Max retries exceeded with URL...

We have reproduced with these tests:

import requests,json
from unitest import TestCase

HTTPS_URL = "https://google.com"
HTTP_URL = "http://google.com"

class ReproduceSslError(Testcase):

    @mocketize
    def test_mocket_fine(self):
        Entry.single_register(
            Entry.GET,
            HTTP_URL,
            body=json.dumps({"foo":"bar"}),
            headers={"Content-Type": "application/json"}
        )
        response = requests.get(HTTP_URL)

    @mocketize
    def test_mocket_error(self):
        Entry.single_register(
            Entry.GET,
            HTTPS_URL,
            body=json.dumps({"foo":"bar"}),
            headers={"Content-Type": "application/json"}
        )
        response = requests.get(HTTPS_URL)

Expected behavior It should mock HTTPS requests too.

Docker image (please complete the following information):

Additional context

oschwald commented 3 years ago

We are also experiencing this. Our tests were working fine last week but stopped several days ago. The cause appears to be urllib3 1.26.5. If I downgrade to 1.26.4, the tests pass.

mindflayer commented 3 years ago

Thanks for the feedback. Something changed in the way urllib3 deals with HTTPS, I need to spend some time on it.

mindflayer commented 3 years ago

This is what they claim they did:

1.26.5 (2021-05-26)

    Fixed deprecation warnings emitted in Python 3.10.
    Updated vendored six library to 1.16.0.
    Improved performance of URL parser when splitting the authority component.

This is the difference between the two versions: https://github.com/urllib3/urllib3/compare/1.26.4...1.26.5

ghost commented 3 years ago

My 2cents As a partial solution, we have mocked urllib3.connection.match_hostname to silence this and it works. This function consumes SSLSocket.getpeercert (override by MocketSocket?) around these functions should be the error.

@mock.patch("urllib3.connection.match_hostname", side_effect=None)
mindflayer commented 3 years ago

I bet this will help me to fix the issue. I was trying to make it happen patching the SSLContext but I was struggling at that.

mindflayer commented 3 years ago

It looks like it was not the only issue brought by the urllib3 upgrade.

mindflayer commented 3 years ago

Here is a new version compatible with the current urllib3: https://pypi.org/project/mocket/3.9.42/

It has been hard but I managed to remove some code and make the rest simpler.