diff options
author | Haibo Huang <hhb@google.com> | 2019-10-01 21:50:26 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-10-01 21:50:26 -0700 |
commit | ad6153f520dcca2e47173a870f3ae82f51f2d187 (patch) | |
tree | 3ed7928f67b78d15fde5300b5e2f203abe05f2ee | |
parent | 534a227325dc3dff5ea339cf464034ff1840f848 (diff) | |
parent | b651919b56ba655ef4845bfaddcb3bb37871a71a (diff) | |
download | platform_external_python_httplib2-ad6153f520dcca2e47173a870f3ae82f51f2d187.tar.gz platform_external_python_httplib2-ad6153f520dcca2e47173a870f3ae82f51f2d187.tar.bz2 platform_external_python_httplib2-ad6153f520dcca2e47173a870f3ae82f51f2d187.zip |
Upgrade python/httplib2 to v0.14.0
am: b651919b56
Change-Id: I94af1a904279c5c512e981d0b4e703d452fc47db
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | .travis.yml | 26 | ||||
-rw-r--r-- | CHANGELOG | 19 | ||||
-rw-r--r-- | METADATA | 6 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | python2/httplib2/__init__.py | 2 | ||||
-rw-r--r-- | python3/httplib2/__init__.py | 41 | ||||
-rw-r--r-- | python3/httplib2/socks.py | 22 | ||||
-rw-r--r-- | script/compile-py3-openssl11.sh | 60 | ||||
-rwxr-xr-x | script/release | 23 | ||||
-rw-r--r-- | setup.cfg | 5 | ||||
-rwxr-xr-x | setup.py | 2 | ||||
-rw-r--r-- | tests/__init__.py | 5 | ||||
-rw-r--r-- | tests/test_external.py | 31 | ||||
-rw-r--r-- | tests/test_http.py | 37 | ||||
-rw-r--r-- | tests/test_proxy.py | 29 |
16 files changed, 260 insertions, 51 deletions
@@ -12,6 +12,7 @@ .project .pydevproject .pytest_cache/* +.tags* .tox _httplib2_test_cache/* bin diff --git a/.travis.yml b/.travis.yml index 57991d5..ca91b60 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,6 @@ env: - pip_install_common='pip>=9.0 setuptools>=36.2 wheel>=0.30' python: - 2.7 - - 3.4 - 3.5 - 3.6 - 3.7 @@ -39,23 +38,32 @@ jobs: script: test_group=pep8 script/test - stage: test env: _=py3-pep8 - python: 3.6 + python: 3.7 install: pip install -r requirements-test.txt script: test_group=pep8 script/test - stage: test + env: _-py37-openssl11 + python: 3.7 # we'll use compiled version but makes Travis look correct + install: + - deactivate && rm -rf $HOME/virtualenv + - source script/compile-py3-openssl11.sh # source to alter PATH + - pip install virtualenv && virtualenv $HOME/virtualenv && source $HOME/virtualenv/bin/activate + - pip install $pip_install_common -r requirements-test.txt + script: script/test -sv + - stage: test env: _=py2-package python: 2.7 install: pip install $pip_install_common script: test_group=package script/test - stage: test env: _=py3-package - python: 3.6 + python: 3.7 install: pip install $pip_install_common script: test_group=package script/test - stage: release if: (branch = master) env: _=pypi-upload-test - python: 3.6 + python: 3.7 install: pip install $pip_install_common script: script/release -auto deploy: @@ -64,16 +72,14 @@ jobs: user: httplib2.release.test password: secure: "XN3oxobC+26UPiS+F1MvL4c6XtytejZ13SkLXCHfgVDPSASzKqF81CnR4EhsnbfZLvSgGHgSlfY5Jve5HF2VR9GzpJMc6wzcfkkeBg6PeRHuMppIqmuoq7BTw81SZL9X62/mju/vxXs2cHpVkwNTSE7W1JH1bVXPj86oAR9xXo9waRuXcyPGNuSqmOd1NPOMbFmeuz+HeArk2Fz7wwo6H5BJuXjOrEOHWD1rzeRchH901PBUrftm54Id2TIVMARW8jm1saQY2FtPWaBv2v/DJC1fKWMJpcNQ3mmcvrrTFC1IJ00dk9XJfqx5hnsRaergc0UvzHoOGEQKSMdg0PUAkvNohAoCf+3GddPkvk8MaZ+aQlijoK6wp93A5dfTxBVZqdhmEdheolbYiJPunzS60bWvaEv6/D15/xyMiwGamUmF1Tx7UIvvm/zj6tAOBWbNEgLRyvQ0qx2RE95GLtp+RXK4pT+Kig1+cof5hrWODuEl1SSLMBySaNLWO73IN9esZu0X1JS7svnROLRJCAvRjppJYswwCPziP+B8XQDeMrhIDMHNzdbtxOPpBAXpYUE764FkzaUTMsK83Q+ugE3Dx8xtrAzT4M0fdiFv+3QEhSUtfvWsLH9zS9wXC5Px9kPKU3FO8mdUyf7A0bIasvJLNcApDJigKjBukToOIsZVFok=" - # TODO: sdist bdist_wheel - # but wheels don't roll well with our 2/3 split code base - distributions: "sdist" + distributions: "sdist bdist_wheel" skip_cleanup: true on: repo: httplib2/httplib2 - stage: release if: (tag IS present) env: _=pypi-upload-public - python: 3.6 + python: 3.7 install: pip install $pip_install_common script: script/release -auto deploy: @@ -81,9 +87,7 @@ jobs: user: httplib2.release password: secure: "jZAyMFnmbhYChjsb3gRYfESWlio6pgmWEWBRxtBQXYZf+tzyKVISyHuyWkJvOVTP+lOpp2MTPZ2s1UgxGwfzZ/VE034Cz5iA/C6wafmgtSW+wK+KEJFPseHBBA7Gh4ReiAPi2a+i1UXdsJpFNhv36E9tbTq2sEinbisE2lSEQ0KHadjkc+6pvCjlyhmes7QyM5GviWYlWRNj2OIkT8SUuUcWQt7ZEl6kN82MoMHCaf1YxE/i4JUP3VLomWK3RLZJP356Y4IDkzlVhFU4MJ4ubNtoQ/ECM0uQ+nsHzO0k1uGWdF6mMTna7U5gLqUi9rfCK3bLMeVSo+TUCpjI7HkWDaBgVXGTe5dUMJCDfRgqeYa0GnriI74XYJu8NGjMLv30uO58t9E7VQGo2NrFRJDzKAIHANejWnpUPY3XgoN1rlrh52seMjaU2+jO40EC8HvIqeRRwPwhkqCSV2y+IZT2bOFp2nbMWhkUMsxIX7OXt+sy8GvK/ilMleEl7r0tnudsT7lGdnMwXlttI3CIAFGE7E+0zwnxNiMzQDzo+ILVR7ezrCK9M9xVYKGa3i8gkpSn0Fblnltgg7HaEI8YC3rMZe4iu1t0D6cZZUAAp2ZUo3NCJcZ35iUFBhlFvjVDbe2upJgU6GFgtDLjyzCJiKbz8qLRgMFYgT0CGr512e1jBo0=" - # TODO: sdist bdist_wheel - # but wheels don't roll well with our 2/3 split code base - distributions: "sdist" + distributions: "sdist bdist_wheel" skip_cleanup: true on: repo: httplib2/httplib2 @@ -1,3 +1,22 @@ +0.14.0 + + Python3: PROXY_TYPE_SOCKS5 with str user/pass raised TypeError + https://github.com/httplib2/httplib2/pull/145 + +0.13.1 + + Python3: Use no_proxy + https://github.com/httplib2/httplib2/pull/140 + +0.13.0 + + Allow setting TLS max/min versions + https://github.com/httplib2/httplib2/pull/138 + +0.12.3 + + No changes to library. Distribute py3 wheels. + 0.12.1 Catch socket timeouts and clear dead connection @@ -9,10 +9,10 @@ third_party { type: GIT value: "https://github.com/httplib2/httplib2.git" } - version: "v0.12.1" + version: "v0.14.0" last_upgrade_date { year: 2019 - month: 2 - day: 21 + month: 9 + day: 26 } } @@ -1,3 +1,5 @@ +.PHONY: tests + tests: -cd python2 && python2.4 httplib2test.py -cd python2 && python2.5 httplib2test.py diff --git a/python2/httplib2/__init__.py b/python2/httplib2/__init__.py index fee091d..98228e3 100644 --- a/python2/httplib2/__init__.py +++ b/python2/httplib2/__init__.py @@ -19,7 +19,7 @@ __contributors__ = [ "Alex Yu", ] __license__ = "MIT" -__version__ = '0.12.1' +__version__ = '0.14.0' import base64 import calendar diff --git a/python3/httplib2/__init__.py b/python3/httplib2/__init__.py index 8b64c41..4312f30 100644 --- a/python3/httplib2/__init__.py +++ b/python3/httplib2/__init__.py @@ -15,7 +15,7 @@ __contributors__ = [ "Alex Yu", ] __license__ = "MIT" -__version__ = '0.12.1' +__version__ = '0.14.0' import base64 import calendar @@ -173,9 +173,9 @@ DEFAULT_TLS_VERSION = getattr(ssl, "PROTOCOL_TLS", None) or getattr( ssl, "PROTOCOL_SSLv23" ) - def _build_ssl_context( - disable_ssl_certificate_validation, ca_certs, cert_file=None, key_file=None + disable_ssl_certificate_validation, ca_certs, cert_file=None, key_file=None, + maximum_version=None, minimum_version=None, ): if not hasattr(ssl, "SSLContext"): raise RuntimeError("httplib2 requires Python 3.2+ for ssl.SSLContext") @@ -185,6 +185,19 @@ def _build_ssl_context( ssl.CERT_NONE if disable_ssl_certificate_validation else ssl.CERT_REQUIRED ) + # SSLContext.maximum_version and SSLContext.minimum_version are python 3.7+. + # source: https://docs.python.org/3/library/ssl.html#ssl.SSLContext.maximum_version + if maximum_version is not None: + if hasattr(context, "maximum_version"): + context.maximum_version = getattr(ssl.TLSVersion, maximum_version) + else: + raise RuntimeError("setting tls_maximum_version requires Python 3.7 and OpenSSL 1.1 or newer") + if minimum_version is not None: + if hasattr(context, "minimum_version"): + context.minimum_version = getattr(ssl.TLSVersion, minimum_version) + else: + raise RuntimeError("setting tls_minimum_version requires Python 3.7 and OpenSSL 1.1 or newer") + # check_hostname requires python 3.4+ # we will perform the equivalent in HTTPSConnectionWithTimeout.connect() by calling ssl.match_hostname # if check_hostname is not supported. @@ -986,6 +999,10 @@ class ProxyInfo(object): proxy_headers: Additional or modified headers for the proxy connect request. """ + if isinstance(proxy_user, str): + proxy_user = proxy_user.encode() + if isinstance(proxy_pass, str): + proxy_pass = proxy_pass.encode() self.proxy_type, self.proxy_host, self.proxy_port, self.proxy_rdns, self.proxy_user, self.proxy_pass, self.proxy_headers = ( proxy_type, proxy_host, @@ -1123,7 +1140,7 @@ class HTTPConnectionWithTimeout(http.client.HTTPConnection): raise ProxiesUnavailableError( "Proxy support missing but proxy use was requested!" ) - if self.proxy_info and self.proxy_info.isgood(): + if self.proxy_info and self.proxy_info.isgood() and self.proxy_info.applies_to(self.host): use_proxy = True proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass, proxy_headers = ( self.proxy_info.astuple() @@ -1226,6 +1243,8 @@ class HTTPSConnectionWithTimeout(http.client.HTTPSConnection): proxy_info=None, ca_certs=None, disable_ssl_certificate_validation=False, + tls_maximum_version=None, + tls_minimum_version=None, ): self.disable_ssl_certificate_validation = disable_ssl_certificate_validation @@ -1236,7 +1255,8 @@ class HTTPSConnectionWithTimeout(http.client.HTTPSConnection): self.proxy_info = proxy_info("https") context = _build_ssl_context( - self.disable_ssl_certificate_validation, self.ca_certs, cert_file, key_file + self.disable_ssl_certificate_validation, self.ca_certs, cert_file, key_file, + maximum_version=tls_maximum_version, minimum_version=tls_minimum_version, ) super(HTTPSConnectionWithTimeout, self).__init__( host, @@ -1384,6 +1404,8 @@ class Http(object): proxy_info=proxy_info_from_environment, ca_certs=None, disable_ssl_certificate_validation=False, + tls_maximum_version=None, + tls_minimum_version=None, ): """If 'cache' is a string then it is used as a directory name for a disk cache. Otherwise it must be an object that supports the @@ -1407,10 +1429,15 @@ class Http(object): If disable_ssl_certificate_validation is true, SSL cert validation will not be performed. + + tls_maximum_version / tls_minimum_version require Python 3.7+ / + OpenSSL 1.1.0g+. A value of "TLSv1_3" requires OpenSSL 1.1.1+. """ self.proxy_info = proxy_info self.ca_certs = ca_certs self.disable_ssl_certificate_validation = disable_ssl_certificate_validation + self.tls_maximum_version = tls_maximum_version + self.tls_minimum_version = tls_minimum_version # Map domain name to an httplib connection self.connections = {} # The location of the cache, for now a directory @@ -1753,6 +1780,8 @@ a string that contains the response entity body. proxy_info=self.proxy_info, ca_certs=self.ca_certs, disable_ssl_certificate_validation=self.disable_ssl_certificate_validation, + tls_maximum_version=self.tls_maximum_version, + tls_minimum_version=self.tls_minimum_version, ) else: conn = self.connections[conn_key] = connection_type( @@ -1761,6 +1790,8 @@ a string that contains the response entity body. proxy_info=self.proxy_info, ca_certs=self.ca_certs, disable_ssl_certificate_validation=self.disable_ssl_certificate_validation, + tls_maximum_version=self.tls_maximum_version, + tls_minimum_version=self.tls_minimum_version, ) else: conn = self.connections[conn_key] = connection_type( diff --git a/python3/httplib2/socks.py b/python3/httplib2/socks.py index 24235df..2926b4e 100644 --- a/python3/httplib2/socks.py +++ b/python3/httplib2/socks.py @@ -206,13 +206,7 @@ class socksocket(socket.socket): return "\r\n".join(hdrs) def __getauthheader(self): - username = self.__proxy[4] - password = self.__proxy[5] - if isinstance(username, str): - username = username.encode() - if isinstance(password, str): - password = password.encode() - auth = username + b":" + password + auth = self.__proxy[4] + b":" + self.__proxy[5] return "Proxy-Authorization: Basic " + base64.b64encode(auth).decode() def setproxy( @@ -273,13 +267,13 @@ class socksocket(socket.socket): elif chosenauth[1:2] == chr(0x02).encode(): # Okay, we need to perform a basic username/password # authentication. - self.sendall( - chr(0x01).encode() - + chr(len(self.__proxy[4])) - + self.__proxy[4] - + chr(len(self.__proxy[5])) - + self.__proxy[5] - ) + packet = bytearray() + packet.append(0x01) + packet.append(len(self.__proxy[4])) + packet.extend(self.__proxy[4]) + packet.append(len(self.__proxy[5])) + packet.extend(self.__proxy[5]) + self.sendall(packet) authstat = self.__recvall(2) if authstat[0:1] != chr(0x01).encode(): # Bad response diff --git a/script/compile-py3-openssl11.sh b/script/compile-py3-openssl11.sh new file mode 100644 index 0000000..3486043 --- /dev/null +++ b/script/compile-py3-openssl11.sh @@ -0,0 +1,60 @@ +#!not for running standalone, see .travis.yml + +cache_dir=$HOME/.cache +install_dir=$cache_dir/py3-openssl11 +python_version="3.7.3" +openssl_version="1.1.1c" +cpucount=$(nproc --all) +export PYTHONDONTWRITEBYTECODE=1 + +#rm -rf $cache_dir/* # uncomment to rebuild + +if [[ $($install_dir/bin/python -V) != "Python $python_version" ]] ; then + ( + mkdir -p /tmp/source + cd /tmp/source + # Compile OpenSSL + wget --quiet https://www.openssl.org/source/openssl-$openssl_version.tar.gz + echo "Extracting OpenSSL..." + tar xf openssl-$openssl_version.tar.gz + cd ./openssl-$openssl_version + echo "Compiling OpenSSL $openssl_version..." + ./config shared --prefix=$install_dir + echo "Running make for OpenSSL..." + make -j$cpucount -s + echo "Running make install for OpenSSL..." + make install_sw >/dev/null + export LD_LIBRARY_PATH=$install_dir/lib + + cd /tmp/source + sudo apt install -qq --yes libffi-dev + # Compile latest Python + wget --quiet https://www.python.org/ftp/python/$python_version/Python-$python_version.tar.xz + echo "Extracting Python..." + tar xf Python-$python_version.tar.xz + cd ./Python-$python_version + echo "Compiling Python $python_version..." + # Note we are purposefully NOT using optimization flags as they increase compile time 10x + conf_flags="--with-openssl=$install_dir --prefix=$install_dir --with-ensurepip=upgrade" + CFLAGS=-O1 ./configure $conf_flags > /dev/null + make -j$cpucount -s + echo "Installing Python..." + make altinstall bininstall >/dev/null + ln -fs pip3.7 $install_dir/bin/pip3 + ln -fs pip3 $install_dir/bin/pip + ln -fs python3 $install_dir/bin/python + # care for CI cache size + find $install_dir -type d -name __pycache__ -print0 |xargs -0 rm -rf + ) +fi + +export LD_LIBRARY_PATH=$install_dir/lib +export PATH=$install_dir/bin:$PATH +if [[ $(python -V) != "Python $python_version" ]] ; then + echo "Required Python version was not installed into PATH" >&2 + exit 1 +fi +if [[ $(python -c 'import ssl; print(ssl.OPENSSL_VERSION)') != OpenSSL\ ${openssl_version}* ]] ; then + echo "Required OpenSSL version was not installed into Python" >&2 + exit 1 +fi diff --git a/script/release b/script/release index 556fc84..0f98e3e 100755 --- a/script/release +++ b/script/release @@ -83,18 +83,17 @@ interactive() { confirm "Continue still? [yN] " || exit 1 fi - echo "Building package" >&2 - find . -name '*.pyc' -o -name '*.pyo' -o -name '*.orig' -delete - rm -rf python{2,3}/.cache - rm -rf build dist - # TODO: sdist bdist_wheel - # but wheels don't roll well with our 2/3 split code base - local venv=./venv-release - if [[ ! -d "$venv" ]] ; then - virtualenv $venv - $venv/bin/pip install -U pip setuptools wheel twine - fi - $venv/bin/python setup.py sdist + echo "Building package" >&2 + find . -name '*.pyc' -o -name '*.pyo' -o -name '*.orig' -delete + rm -rf python{2,3}/.cache + rm -rf build dist + local venv=./venv-release + if [[ ! -d "$venv" ]] ; then + virtualenv $venv + $venv/bin/pip install -U pip setuptools wheel twine + fi + $venv/bin/python setup.py clean --all + $venv/bin/python setup.py sdist bdist_wheel if confirm "Upload to PyPI? Use in special situation, normally CI (Travis) will upload to PyPI. [yN] " ; then $venv/bin/twine upload dist/* || exit 1 @@ -1,3 +1,8 @@ +# [bdist_wheel] +# universal = 1 +# FIXME universal wheels don't roll well with our 2/3 split code base +# https://github.com/httplib2/httplib2/pull/29 + [coverage:run] omit = */test/* @@ -4,7 +4,7 @@ import setuptools.command.test import sys pkgdir = {"": "python%s" % sys.version_info[0]} -VERSION = '0.12.1' +VERSION = '0.14.0' # `python setup.py test` uses existing Python environment, no virtualenv, no pip. diff --git a/tests/__init__.py b/tests/__init__.py index 69d7d10..28959d3 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -269,7 +269,8 @@ def server_socket(fun, request_count=1, timeout=5): gcounter[0] += 1 keep = True keep &= gcounter[0] < request_count - keep &= request.headers.get("connection", "").lower() != "close" + if request is not None: + keep &= request.headers.get("connection", "").lower() != "close" return keep def server_socket_thread(srv): @@ -295,7 +296,7 @@ def server_socket(fun, request_count=1, timeout=5): ) except Exception as e: # traceback.print_exc caused IOError: concurrent operation on sys.stderr.close() under setup.py test - sys.stderr.write(traceback.format_exc().encode()) + print(traceback.format_exc(), file=sys.stderr) gresult[0] = e server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) diff --git a/tests/test_external.py b/tests/test_external.py index 10b0d8b..0628d96 100644 --- a/tests/test_external.py +++ b/tests/test_external.py @@ -96,3 +96,34 @@ def test_sni_hostname_validation(): # TODO: make explicit test server with SNI validation http = httplib2.Http() http.request("https://google.com/", method="GET") + + +@pytest.mark.skipif( + os.environ.get("TRAVIS_PYTHON_VERSION") in ("2.7", "pypy"), + reason="Python 2.7 doesn't support TLS min/max" +) +def test_min_tls_version(): + # skip on Python versions that don't support TLS min + if not hasattr(ssl.SSLContext(), 'minimum_version'): + return + # BadSSL server that supports max TLS 1.1, + # forcing 1.2 should always fail + http = httplib2.Http(tls_minimum_version="TLSv1_2") + with tests.assert_raises(ssl.SSLError): + http.request("https://tls-v1-1.badssl.com:1011/") + + +@pytest.mark.skipif( + os.environ.get("TRAVIS_PYTHON_VERSION") in ("2.7", "pypy"), + reason="Python 2.7 doesn't support TLS min/max" +) +def test_max_tls_version(): + # skip on Python versions that don't support TLS max + if not hasattr(ssl.SSLContext(), 'maximum_version'): + return + # Google supports TLS 1.2+, confirm we can force down to 1.0 + # this may break whenever Google disables TLSv1 + http = httplib2.Http(tls_maximum_version="TLSv1") + http.request("https://google.com") + _, tls_ver, _ = http.connections['https:google.com'].sock.cipher() + assert tls_ver == "TLSv1.0" diff --git a/tests/test_http.py b/tests/test_http.py index 2bee6ca..9bd9ee0 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -10,9 +10,11 @@ import os import pytest from six.moves import http_client, urllib import socket +import ssl import tests DUMMY_URL = "http://127.0.0.1:1" +DUMMY_HTTPS_URL = "https://127.0.0.1:2" def _raise_connection_refused_exception(*args, **kwargs): @@ -645,3 +647,38 @@ content""" assert response.status == 200 assert content == b"content" assert response["link"], "link1, link2" + + +@pytest.mark.skipif( + os.environ.get("TRAVIS_PYTHON_VERSION") in ("2.7", "pypy"), + reason="Python 2.7 doesn't support TLS min/max" +) +def test_set_min_tls_version(): + # Test setting minimum TLS version + # We expect failure on Python < 3.7 or OpenSSL < 1.1 + expect_success = hasattr(ssl.SSLContext(), 'minimum_version') + try: + http = httplib2.Http(tls_minimum_version="TLSv1_2") + http.request(DUMMY_HTTPS_URL) + except RuntimeError: + assert not expect_success + except socket.error: + assert expect_success + + +@pytest.mark.skipif( + os.environ.get("TRAVIS_PYTHON_VERSION") in ("2.7", "pypy"), + reason="Python 2.7 doesn't support TLS min/max" +) +def test_set_max_tls_version(): + # Test setting maximum TLS version + # We expect RuntimeError on Python < 3.7 or OpenSSL < 1.1 + # We expect socket error otherwise + expect_success = hasattr(ssl.SSLContext(), 'maximum_version') + try: + http = httplib2.Http(tls_maximum_version="TLSv1_2") + http.request(DUMMY_HTTPS_URL) + except RuntimeError: + assert not expect_success + except socket.error: + assert expect_success diff --git a/tests/test_proxy.py b/tests/test_proxy.py index 56a7d99..375367f 100644 --- a/tests/test_proxy.py +++ b/tests/test_proxy.py @@ -32,8 +32,8 @@ def test_from_url_ident(): pi = httplib2.proxy_info_from_url("http://zoidberg:fish@someproxy:99") assert pi.proxy_host == "someproxy" assert pi.proxy_port == 99 - assert pi.proxy_user == "zoidberg" - assert pi.proxy_pass == "fish" + assert pi.proxy_user == b"zoidberg" + assert pi.proxy_pass == b"fish" def test_from_env(): @@ -146,3 +146,28 @@ def test_auth_str_bytes(): ) response, _ = http.request(uri, "GET") assert response.status == 200 + + +def test_socks5_auth(): + def proxy_conn(client, tick): + data = client.recv(64) + assert data == b"\x05\x02\x00\x02" + client.send(b"\x05\x02") # select username/password auth + data = client.recv(64) + assert data == b"\x01\x08user_str\x08pass_str" + client.send(b"\x01\x01") # deny + tick(None) + + with tests.server_socket(proxy_conn) as uri: + uri_parsed = urllib.parse.urlparse(uri) + proxy_info = httplib2.ProxyInfo( + httplib2.socks.PROXY_TYPE_SOCKS5, + proxy_host=uri_parsed.hostname, + proxy_port=uri_parsed.port, + proxy_rdns=True, + proxy_user=u"user_str", + proxy_pass=u"pass_str", + ) + http = httplib2.Http(proxy_info=proxy_info) + with tests.assert_raises(httplib2.socks.Socks5AuthError): + http.request(uri, "GET") |