Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: urllib3/urllib3
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1.26.8
Choose a base ref
...
head repository: urllib3/urllib3
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1.26.9
Choose a head ref
  • 10 commits
  • 18 files changed
  • 4 contributors

Commits on Jan 20, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f1d40fd View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    778e585 View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d662fcd View commit details

Commits on Jan 21, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a4539fb View commit details

Commits on Jan 24, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    048c0ba View commit details

Commits on Jan 30, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    834dd1e View commit details

Commits on Feb 10, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5cf6d03 View commit details

Commits on Mar 3, 2022

  1. [1.26] Avoid socket leak if HTTPSConnection.connect() fails

    Co-authored-by: Thomas Grainger <tagrain@gmail.com>
    sethmlarson and graingert authored Mar 3, 2022

    Partially verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.
    Copy the full SHA
    c0a182c View commit details

Commits on Mar 15, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5ea33e1 View commit details

Commits on Mar 16, 2022

  1. Release 1.26.9

    sethmlarson authored Mar 16, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6de3330 View commit details
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -117,7 +117,7 @@ jobs:
run: |
python -m coverage combine
python -m coverage html --skip-covered --skip-empty
python -m coverage report -i --fail-under=100
python -m coverage report --ignore-errors --show-missing --fail-under=100
- name: "Upload report if check failed"
uses: actions/upload-artifact@v2
13 changes: 12 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
Changes
=======

1.26.9 (2022-03-16)
-------------------

* Changed ``urllib3[brotli]`` extra to favor installing Brotli libraries that are still
receiving updates like ``brotli`` and ``brotlicffi`` instead of ``brotlipy``.
This change does not impact behavior of urllib3, only which dependencies are installed.
* Fixed a socket leaking when ``HTTPSConnection.connect()`` raises an exception.
* Fixed ``server_hostname`` being forwarded from ``PoolManager`` to ``HTTPConnectionPool``
when requesting an HTTP URL. Should only be forwarded when requesting an HTTPS URL.


1.26.8 (2022-01-07)
-------------------

* Added extra message to``urllib3.exceptions.ProxyError`` when urllib3 detects that
* Added extra message to ``urllib3.exceptions.ProxyError`` when urllib3 detects that
a proxy is configured to use HTTPS but the proxy itself appears to only use HTTP.
* Added a mention of the size of the connection pool when discarding a connection due to the pool being full.
* Added explicit support for Python 3.11.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
@@ -52,7 +52,7 @@ urllib3 can be installed with `pip <https://pip.pypa.io>`_::
Alternatively, you can grab the latest source code from `GitHub <https://github.com/urllib3/urllib3>`_::

$ git clone git://github.com/urllib3/urllib3.git
$ python setup.py install
$ pip install .


Documentation
3 changes: 2 additions & 1 deletion docs/advanced-usage.rst
Original file line number Diff line number Diff line change
@@ -454,7 +454,8 @@ Brotli Encoding

Brotli is a compression algorithm created by Google with better compression
than gzip and deflate and is supported by urllib3 if the
`brotlipy <https://github.com/python-hyper/brotlipy>`_ package is installed.
`Brotli <https://pypi.org/Brotli>`_ package or
`brotlicffi <https://github.com/python-hyper/brotlicffi>`_ package is installed.
You may also request the package be installed via the ``urllib3[brotli]`` extra:

.. code-block:: bash
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
@@ -86,7 +86,7 @@ Alternatively, you can grab the latest source code from `GitHub <https://github.
.. code-block:: bash
$ git clone git://github.com/urllib3/urllib3.git
$ python setup.py install
$ pip install .
Usage
-----
4 changes: 3 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -19,7 +19,9 @@ requires-dist =
certifi; extra == 'secure'
ipaddress; python_version=="2.7" and extra == 'secure'
PySocks>=1.5.6,<2.0,!=1.5.7; extra == 'socks'
brotlipy>=0.6.0; extra == 'brotli'
brotli>=1.0.9; (os_name != 'nt' or python_version >= '3') and platform_python_implementation == 'CPython' and extra == 'brotli'
brotlicffi>=0.8.0; (os_name != 'nt' or python_version >= '3') and platform_python_implementation != 'CPython' and extra == 'brotli'
brotlipy>=0.6.0; os_name == 'nt' and python_version < '3' and extra == 'brotli'

[tool:pytest]
xfail_strict = true
6 changes: 5 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -85,7 +85,11 @@
requires=[],
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4",
extras_require={
"brotli": ["brotlipy>=0.6.0"],
"brotli": [
"brotli>=1.0.9; (os_name != 'nt' or python_version >= '3') and platform_python_implementation == 'CPython'",
"brotlicffi>=0.8.0; (os_name != 'nt' or python_version >= '3') and platform_python_implementation != 'CPython'",
"brotlipy>=0.6.0; os_name == 'nt' and python_version < '3'",
],
"secure": [
"pyOpenSSL>=0.14",
"cryptography>=1.3.4",
2 changes: 1 addition & 1 deletion src/urllib3/_version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# This file is protected via CODEOWNERS
__version__ = "1.26.8"
__version__ = "1.26.9"
6 changes: 2 additions & 4 deletions src/urllib3/connection.py
Original file line number Diff line number Diff line change
@@ -355,17 +355,15 @@ def set_cert(

def connect(self):
# Add certificate verification
conn = self._new_conn()
self.sock = conn = self._new_conn()
hostname = self.host
tls_in_tls = False

if self._is_using_tunnel():
if self.tls_in_tls_required:
conn = self._connect_tls_proxy(hostname, conn)
self.sock = conn = self._connect_tls_proxy(hostname, conn)
tls_in_tls = True

self.sock = conn

# Calls self._set_hostport(), so self.host is
# self._tunnel_host below.
self._tunnel()
1 change: 1 addition & 0 deletions src/urllib3/poolmanager.py
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@
"ca_cert_dir",
"ssl_context",
"key_password",
"server_hostname",
)

# All known keyword arguments that could be provided to the pool manager, its
5 changes: 4 additions & 1 deletion src/urllib3/response.py
Original file line number Diff line number Diff line change
@@ -8,7 +8,10 @@
from socket import timeout as SocketTimeout

try:
import brotli
try:
import brotlicffi as brotli
except ImportError:
import brotli
except ImportError:
brotli = None

5 changes: 4 additions & 1 deletion src/urllib3/util/request.py
Original file line number Diff line number Diff line change
@@ -14,7 +14,10 @@

ACCEPT_ENCODING = "gzip,deflate"
try:
import brotli as _unused_module_brotli # noqa: F401
try:
import brotlicffi as _unused_module_brotli # noqa: F401
except ImportError:
import brotli as _unused_module_brotli # noqa: F401
except ImportError:
pass
else:
10 changes: 4 additions & 6 deletions src/urllib3/util/ssl_match_hostname.py
Original file line number Diff line number Diff line change
@@ -112,19 +112,17 @@ def match_hostname(cert, hostname):
try:
# Divergence from upstream: ipaddress can't handle byte str
host_ip = ipaddress.ip_address(_to_unicode(hostname))
except ValueError:
# Not an IP address (common case)
host_ip = None
except UnicodeError:
# Divergence from upstream: Have to deal with ipaddress not taking
except (UnicodeError, ValueError):
# ValueError: Not an IP address (common case)
# UnicodeError: Divergence from upstream: Have to deal with ipaddress not taking
# byte strings. addresses should be all ascii, so we consider it not
# an ipaddress in this case
host_ip = None
except AttributeError:
# Divergence from upstream: Make ipaddress library optional
if ipaddress is None:
host_ip = None
else:
else: # Defensive
raise
dnsnames = []
san = cert.get("subjectAltName", ())
5 changes: 4 additions & 1 deletion test/__init__.py
Original file line number Diff line number Diff line change
@@ -10,7 +10,10 @@
import pytest

try:
import brotli
try:
import brotlicffi as brotli
except ImportError:
import brotli
except ImportError:
brotli = None

10 changes: 10 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
@@ -103,6 +103,16 @@ def no_san_server(tmp_path_factory):
yield cfg


@pytest.fixture()
def no_san_server_with_different_commmon_name(tmp_path_factory):
tmpdir = tmp_path_factory.mktemp("certs")
ca = trustme.CA()
server_cert = ca.issue_cert(common_name=u"example.com")

with run_server_in_thread("https", "localhost", tmpdir, ca, server_cert) as cfg:
yield cfg


@pytest.fixture
def no_san_proxy(tmp_path_factory):
tmpdir = tmp_path_factory.mktemp("certs")
6 changes: 6 additions & 0 deletions test/test_connection.py
Original file line number Diff line number Diff line change
@@ -28,6 +28,12 @@ def test_match_hostname_match(self):
asserted_hostname = "foo"
_match_hostname(cert, asserted_hostname)

def test_match_hostname_ipaddress_none(self):
cert = {"subjectAltName": [("DNS", "foo")]}
asserted_hostname = "foo"
with mock.patch("urllib3.util.ssl_match_hostname.ipaddress", None):
assert _match_hostname(cert, asserted_hostname) is None

def test_match_hostname_mismatch(self):
cert = {"subjectAltName": [("DNS", "foo")]}
asserted_hostname = "bar"
29 changes: 29 additions & 0 deletions test/with_dummyserver/test_https.py
Original file line number Diff line number Diff line change
@@ -336,6 +336,22 @@ def test_verified_with_bad_ca_certs(self):
"Expected 'certificate verify failed', instead got: %r" % e.value.reason
)

def test_wrap_socket_failure_resource_leak(self):
with HTTPSConnectionPool(
self.host,
self.port,
cert_reqs="CERT_REQUIRED",
ca_certs=self.bad_ca_path,
) as https_pool:
conn = https_pool._get_conn()
try:
with pytest.raises(ssl.SSLError):
conn.connect()

assert conn.sock
finally:
conn.close()

def test_verified_without_ca_certs(self):
# default is cert_reqs=None which is ssl.CERT_NONE
with HTTPSConnectionPool(
@@ -858,6 +874,19 @@ def test_warning_for_certs_without_a_san(self, no_san_server):
assert r.status == 200
assert warn.called

def test_common_name_without_san_with_different_common_name(
self, no_san_server_with_different_commmon_name
):
with HTTPSConnectionPool(
no_san_server_with_different_commmon_name.host,
no_san_server_with_different_commmon_name.port,
cert_reqs="CERT_REQUIRED",
ca_certs=no_san_server_with_different_commmon_name.ca_certs,
) as https_pool:
with pytest.raises(MaxRetryError) as cm:
https_pool.request("GET", "/")
assert isinstance(cm.value.reason, SSLError)


class TestHTTPS_IPV4SAN:
def test_can_validate_ip_san(self, ipv4_san_server):
5 changes: 5 additions & 0 deletions test/with_dummyserver/test_poolmanager.py
Original file line number Diff line number Diff line change
@@ -346,6 +346,11 @@ def test_http_with_ssl_keywords(self):
r = http.request("GET", "http://%s:%s/" % (self.host, self.port))
assert r.status == 200

def test_http_with_server_hostname(self):
with PoolManager(server_hostname="example.com") as http:
r = http.request("GET", "http://%s:%s/" % (self.host, self.port))
assert r.status == 200

def test_http_with_ca_cert_dir(self):
with PoolManager(ca_certs="REQUIRED", ca_cert_dir="/nosuchdir") as http:
r = http.request("GET", "http://%s:%s/" % (self.host, self.port))