-
Notifications
You must be signed in to change notification settings - Fork 11
urllib3 1.24.1 to 1.25.3
mickael e edited this page Aug 16, 2019
·
1 revision
de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22 urllib3-1.24.1.tar.gz
dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232 urllib3-1.25.3.tar.gz
--- urllib3-1.24.1.tar.gz
+++ urllib3-1.25.3.tar.gz
├── metadata
│ @@ -1 +1 @@
│ -gzip compressed data, was "dist/urllib3-1.24.1.tar", last modified: Fri Nov 2 19:11:08 2018, max compression
│ +gzip compressed data, was "dist/urllib3-1.25.3.tar", last modified: Thu May 23 19:01:43 2019, max compression
│ --- urllib3-1.24.1.tar
├── +++ urllib3-1.25.3.tar
├── file list
│ │ @@ -1,152 +1,169 @@
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 29661 2018-11-02 19:08:50.000000 urllib3-1.24.1/CHANGES.rst
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 8997 2018-10-16 17:45:39.000000 urllib3-1.24.1/CONTRIBUTORS.txt
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1175 2018-10-05 21:00:05.000000 urllib3-1.24.1/LICENSE.txt
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 204 2018-10-05 21:00:05.000000 urllib3-1.24.1/MANIFEST.in
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1192 2018-10-05 21:00:05.000000 urllib3-1.24.1/Makefile
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 43238 2018-11-02 19:11:08.000000 urllib3-1.24.1/PKG-INFO
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 3780 2018-10-05 21:00:05.000000 urllib3-1.24.1/README.rst
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 292 2018-11-02 19:07:12.000000 urllib3-1.24.1/dev-requirements.txt
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/docs/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 4602 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/Makefile
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/docs/_templates/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 106 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/_templates/fonts.html
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 9700 2018-10-16 17:45:39.000000 urllib3-1.24.1/docs/advanced-usage.rst
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 8388 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/conf.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 3699 2018-10-16 17:45:39.000000 urllib3-1.24.1/docs/contributing.rst
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1889 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/index.rst
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 4513 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/make.bat
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/docs/reference/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1434 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/reference/index.rst
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 838 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/reference/urllib3.contrib.rst
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1539 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/reference/urllib3.util.rst
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 80 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/requirements.txt
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 13677 2018-10-05 21:00:05.000000 urllib3-1.24.1/docs/user-guide.rst
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/dummyserver/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 0 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/__init__.py
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/dummyserver/certs/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 620 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/README.rst
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/dummyserver/certs/ca_path_test/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1379 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/ca_path_test/98a2772e.0
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1379 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/ca_path_test/b6b9ccf9.0
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1379 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/ca_path_test/cacert.pem
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 891 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/cacert.key
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1827 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/cacert.no_san.pem
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1379 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/cacert.pem
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1391 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/client.csr
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 887 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/client.key
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1257 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/client.pem
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 993 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/client_bad.pem
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 887 2018-10-16 17:45:39.000000 urllib3-1.24.1/dummyserver/certs/client_intermediate.key
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1953 2018-10-16 17:45:39.000000 urllib3-1.24.1/dummyserver/certs/client_intermediate.pem
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 936 2018-10-16 17:45:39.000000 urllib3-1.24.1/dummyserver/certs/client_no_intermediate.pem
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 887 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/intermediate.key
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1054 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/intermediate.pem
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 2148 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.combined.pem
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1257 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.crt
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1330 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.csr
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1265 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.ip_san.crt
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 956 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.ipv6addr.crt
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1679 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.ipv6addr.key
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 891 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.key
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 561 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.key.org
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 936 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.no_san.crt
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 696 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/certs/server.no_san.csr
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 11886 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/handlers.py
│ │ --rwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 4756 2018-10-05 21:00:05.000000 urllib3-1.24.1/dummyserver/proxy.py
│ │ --rwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 9430 2018-10-16 17:45:39.000000 urllib3-1.24.1/dummyserver/server.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 6470 2018-10-16 17:45:39.000000 urllib3-1.24.1/dummyserver/testcase.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 550 2018-11-02 19:11:08.000000 urllib3-1.24.1/setup.cfg
│ │ --rwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 2684 2018-10-16 17:45:39.000000 urllib3-1.24.1/setup.py
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 2722 2018-11-02 19:09:02.000000 urllib3-1.24.1/src/urllib3/__init__.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 10746 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/_collections.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 13839 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/connection.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 35097 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/connectionpool.py
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/contrib/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 0 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/__init__.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 717 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/_appengine_environ.py
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/contrib/_securetransport/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 0 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/_securetransport/__init__.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 17560 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/_securetransport/bindings.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 12162 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/_securetransport/low_level.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 10914 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/appengine.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 4459 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/ntlmpool.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 15806 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/pyopenssl.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 30309 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/securetransport.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 6391 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/contrib/socks.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 6604 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/exceptions.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 5943 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/fields.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 2436 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/filepost.py
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/packages/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 109 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/packages/__init__.py
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/packages/backports/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 0 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/packages/backports/__init__.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1456 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/packages/backports/makefile.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 30098 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/packages/six.py
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/packages/ssl_match_hostname/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 688 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/packages/ssl_match_hostname/__init__.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 5683 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/packages/ssl_match_hostname/_implementation.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 16853 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/poolmanager.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 5991 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/request.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 25609 2018-11-02 19:07:12.000000 urllib3-1.24.1/src/urllib3/response.py
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3/util/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1044 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/__init__.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 4639 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/connection.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 497 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/queue.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 3705 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/request.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 2586 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/response.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 15105 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/retry.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 13143 2018-11-02 19:07:12.000000 urllib3-1.24.1/src/urllib3/util/ssl_.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 9757 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/timeout.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 6487 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/url.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 5403 2018-10-16 17:45:39.000000 urllib3-1.24.1/src/urllib3/util/wait.py
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3.egg-info/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 43238 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3.egg-info/PKG-INFO
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 3840 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3.egg-info/SOURCES.txt
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3.egg-info/dependency_links.txt
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 113 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3.egg-info/requires.txt
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 8 2018-11-02 19:11:08.000000 urllib3-1.24.1/src/urllib3.egg-info/top_level.txt
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/test/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 4210 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/__init__.py
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/test/appengine/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 0 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/appengine/__init__.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 2231 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/appengine/conftest.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 6435 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/appengine/test_gae_manager.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 2547 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/appengine/test_urlfetch.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 2086 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/benchmark.py
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/test/contrib/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 0 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/contrib/__init__.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1257 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/contrib/duplicate_san.pem
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 2675 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/contrib/test_pyopenssl.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1760 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/contrib/test_pyopenssl_dependencies.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 992 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/contrib/test_securetransport.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 23210 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/contrib/test_socks.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 5702 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/port_helpers.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 2424 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/socketpair_helper.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 10471 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_collections.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1426 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_compatibility.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1875 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_connection.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 17446 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_connectionpool.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1390 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_exceptions.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 2631 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_fields.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 4201 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_filepost.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 2219 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/test_no_ssl.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 13688 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/test_poolmanager.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 1672 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_proxymanager.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 808 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_queue_monkeypatch.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 26999 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/test_response.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 10713 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/test_retry.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 2656 2018-11-02 19:07:12.000000 urllib3-1.24.1/test/test_ssl.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 22603 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/test_util.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 5506 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/test_wait.py
│ │ -drwxr-xr-x 0 theaflowers (297975) primarygroup (297975) 0 2018-11-02 19:11:08.000000 urllib3-1.24.1/test/with_dummyserver/
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 0 2018-10-05 21:00:05.000000 urllib3-1.24.1/test/with_dummyserver/__init__.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 4002 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_chunked_transfer.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 41165 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_connectionpool.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 26075 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_https.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 933 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_no_ssl.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 10641 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_poolmanager.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 15183 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_proxy_poolmanager.py
│ │ --rw-r--r-- 0 theaflowers (297975) primarygroup (297975) 53266 2018-10-16 17:45:39.000000 urllib3-1.24.1/test/with_dummyserver/test_socketlevel.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 31939 2019-05-23 19:01:31.000000 urllib3-1.25.3/CHANGES.rst
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 9141 2019-05-23 19:01:31.000000 urllib3-1.25.3/CONTRIBUTORS.txt
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1115 2019-05-23 19:01:31.000000 urllib3-1.25.3/LICENSE.txt
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 204 2019-05-23 19:01:31.000000 urllib3-1.25.3/MANIFEST.in
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1192 2019-05-23 19:01:31.000000 urllib3-1.25.3/Makefile
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 47286 2019-05-23 19:01:43.000000 urllib3-1.25.3/PKG-INFO
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 4683 2019-05-23 19:01:31.000000 urllib3-1.25.3/README.rst
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 359 2019-05-23 19:01:31.000000 urllib3-1.25.3/dev-requirements.txt
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/docs/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 4602 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/Makefile
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/docs/_templates/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 106 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/_templates/fonts.html
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 10764 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/advanced-usage.rst
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 8389 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/conf.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 5304 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/contributing.rst
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1889 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/index.rst
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 4513 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/make.bat
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/docs/reference/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1434 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/reference/index.rst
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 838 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/reference/urllib3.contrib.rst
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1539 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/reference/urllib3.util.rst
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 62 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/requirements.txt
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 13781 2019-05-23 19:01:31.000000 urllib3-1.25.3/docs/user-guide.rst
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/dummyserver/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 0 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/__init__.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/dummyserver/certs/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 620 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/README.rst
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/dummyserver/certs/ca_path_test/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1379 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/ca_path_test/98a2772e.0
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1379 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/ca_path_test/b6b9ccf9.0
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1379 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/ca_path_test/cacert.pem
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 891 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/cacert.key
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1827 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/cacert.no_san.pem
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1379 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/cacert.pem
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1391 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client.csr
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 887 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client.key
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1257 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client.pem
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 993 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client_bad.pem
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 887 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client_intermediate.key
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1953 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client_intermediate.pem
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 936 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client_no_intermediate.pem
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 986 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/client_password.key
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 887 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/intermediate.key
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1054 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/intermediate.pem
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 2148 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.combined.pem
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1257 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.crt
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1330 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.csr
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1265 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.ip_san.crt
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 924 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.ipv6_san.crt
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 956 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.ipv6addr.crt
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1679 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.ipv6addr.key
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 891 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.key
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 561 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.key.org
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 936 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.no_san.crt
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 696 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server.no_san.csr
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 986 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/certs/server_password.key
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 10657 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/handlers.py
│ │ +-rwxrwxr-x 0 travis (2000) travis (2000) 4756 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/proxy.py
│ │ +-rwxrwxr-x 0 travis (2000) travis (2000) 9759 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/server.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 6470 2019-05-23 19:01:31.000000 urllib3-1.25.3/dummyserver/testcase.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 550 2019-05-23 19:01:43.000000 urllib3-1.25.3/setup.cfg
│ │ +-rwxrwxr-x 0 travis (2000) travis (2000) 2901 2019-05-23 19:01:31.000000 urllib3-1.25.3/setup.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 2721 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/__init__.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 10746 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/_collections.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 15001 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/connection.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 35307 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/connectionpool.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/contrib/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 0 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/__init__.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 717 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/_appengine_environ.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/contrib/_securetransport/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 0 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/_securetransport/__init__.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 17576 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/_securetransport/bindings.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 12162 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/_securetransport/low_level.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 10914 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/appengine.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 4459 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/ntlmpool.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 16451 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/pyopenssl.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 32826 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/securetransport.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 7012 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/contrib/socks.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 6604 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/exceptions.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 8575 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/fields.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 2436 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/filepost.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/packages/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 109 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/__init__.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/packages/backports/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 0 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/backports/__init__.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1456 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/backports/makefile.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1562 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/__init__.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 13214 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/_mixin.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 9081 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/abnf_regexp.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 3887 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/api.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 9577 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/builder.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1513 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/compat.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 3775 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/exceptions.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 5466 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/iri.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 4094 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/misc.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 5259 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/normalizers.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 14654 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/parseresult.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 5227 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/uri.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 13854 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/rfc3986/validators.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 30098 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/six.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/packages/ssl_match_hostname/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 688 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/ssl_match_hostname/__init__.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 5683 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/packages/ssl_match_hostname/_implementation.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 17050 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/poolmanager.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 5991 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/request.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 27171 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/response.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3/util/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1082 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/__init__.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 4639 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/connection.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 497 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/queue.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 3832 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/request.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 2586 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/response.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 15150 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/retry.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 13786 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/ssl_.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 9768 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/timeout.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 9810 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/url.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 5403 2019-05-23 19:01:31.000000 urllib3-1.25.3/src/urllib3/util/wait.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3.egg-info/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 47286 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3.egg-info/PKG-INFO
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 4476 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3.egg-info/SOURCES.txt
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3.egg-info/dependency_links.txt
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 173 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3.egg-info/requires.txt
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 8 2019-05-23 19:01:43.000000 urllib3-1.25.3/src/urllib3.egg-info/top_level.txt
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/test/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 6629 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/__init__.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/test/appengine/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 0 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/appengine/__init__.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 2231 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/appengine/conftest.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 6435 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/appengine/test_gae_manager.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 2547 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/appengine/test_urlfetch.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 2086 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/benchmark.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/test/contrib/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 0 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/contrib/__init__.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1257 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/contrib/duplicate_san.pem
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 2815 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/contrib/test_pyopenssl.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1945 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/contrib/test_pyopenssl_dependencies.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1061 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/contrib/test_securetransport.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 23243 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/contrib/test_socks.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 5702 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/port_helpers.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 2424 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/socketpair_helper.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 10471 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_collections.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1426 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_compatibility.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1875 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_connection.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 17459 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_connectionpool.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1390 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_exceptions.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 4206 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_fields.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 4201 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_filepost.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 2219 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_no_ssl.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 13688 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_poolmanager.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 1672 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_proxymanager.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 808 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_queue_monkeypatch.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 29090 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_response.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 10713 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_retry.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 4074 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_ssl.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 29188 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_util.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 5506 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/test_wait.py
│ │ +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-05-23 19:01:43.000000 urllib3-1.25.3/test/with_dummyserver/
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 0 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/__init__.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 4002 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_chunked_transfer.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 41843 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_connectionpool.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 29216 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_https.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 951 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_no_ssl.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 11616 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_poolmanager.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 14973 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_proxy_poolmanager.py
│ │ +-rw-rw-r-- 0 travis (2000) travis (2000) 58742 2019-05-23 19:01:31.000000 urllib3-1.25.3/test/with_dummyserver/test_socketlevel.py
│ --- urllib3-1.24.1/dummyserver/certs/server.ip_san.crt
├── +++ urllib3-1.25.3/dummyserver/certs/server.ip_san.crt
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/test_connectionpool.py
├── +++ urllib3-1.25.3/test/test_connectionpool.py
│┄ Files similar despite different names (difference score: 2)
│ │ @@ -1,9 +1,10 @@
│ │ from __future__ import absolute_import
│ │
│ │ +import ssl
│ │ import pytest
│ │
│ │ from urllib3.connectionpool import (
│ │ connection_from_url,
│ │ HTTPConnection,
│ │ HTTPConnectionPool,
│ │ HTTPSConnectionPool,
│ │ @@ -346,15 +347,15 @@
│ │ def test_absolute_url(self):
│ │ with connection_from_url('http://google.com:80') as c:
│ │ assert 'http://google.com:80/path?query=foo' == c._absolute_url('path?query=foo')
│ │
│ │ def test_ca_certs_default_cert_required(self):
│ │ with connection_from_url('https://google.com:80', ca_certs=DEFAULT_CA) as pool:
│ │ conn = pool._get_conn()
│ │ - assert conn.cert_reqs == 'CERT_REQUIRED'
│ │ + assert conn.cert_reqs == ssl.CERT_REQUIRED
│ │
│ │ def test_cleanup_on_extreme_connection_error(self):
│ │ """
│ │ This test validates that we clean up properly even on exceptions that
│ │ we'd not otherwise catch, i.e. those that inherit from BaseException
│ │ like KeyboardInterrupt or gevent.Timeout. See #805 for more details.
│ │ """
│ --- urllib3-1.24.1/test/contrib/duplicate_san.pem
├── +++ urllib3-1.25.3/test/contrib/duplicate_san.pem
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/test_poolmanager.py
├── +++ urllib3-1.25.3/test/test_poolmanager.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/docs/make.bat
├── +++ urllib3-1.25.3/docs/make.bat
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/test_connection.py
├── +++ urllib3-1.25.3/test/test_connection.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/util/timeout.py
├── +++ urllib3-1.25.3/src/urllib3/util/timeout.py
│┄ Files similar despite different names (difference score: 1)
│ │ @@ -127,15 +127,16 @@
│ │ "int, float or None." % (name, value))
│ │
│ │ try:
│ │ if value <= 0:
│ │ raise ValueError("Attempted to set %s timeout to %s, but the "
│ │ "timeout cannot be set to a value less "
│ │ "than or equal to 0." % (name, value))
│ │ - except TypeError: # Python 3
│ │ + except TypeError:
│ │ + # Python 3
│ │ raise ValueError("Timeout value %s was %s, but it must be an "
│ │ "int, float or None." % (name, value))
│ │
│ │ return value
│ │
│ │ @classmethod
│ │ def from_float(cls, timeout):
│ --- urllib3-1.24.1/setup.py
├── +++ urllib3-1.25.3/setup.py
│┄ Files similar despite different names (difference score: 15)
│ │ @@ -31,46 +31,51 @@
│ │ 'Programming Language :: Python',
│ │ 'Programming Language :: Python :: 2',
│ │ 'Programming Language :: Python :: 2.7',
│ │ 'Programming Language :: Python :: 3',
│ │ 'Programming Language :: Python :: 3.4',
│ │ 'Programming Language :: Python :: 3.5',
│ │ 'Programming Language :: Python :: 3.6',
│ │ + 'Programming Language :: Python :: 3.7',
│ │ + 'Programming Language :: Python :: 3.8',
│ │ 'Programming Language :: Python :: Implementation :: CPython',
│ │ 'Programming Language :: Python :: Implementation :: PyPy',
│ │ 'Topic :: Internet :: WWW/HTTP',
│ │ 'Topic :: Software Development :: Libraries',
│ │ ],
│ │ keywords='urllib httplib threadsafe filepost http https ssl pooling',
│ │ author='Andrey Petrov',
│ │ author_email='[email protected]',
│ │ url='https://urllib3.readthedocs.io/',
│ │ license='MIT',
│ │ packages=['urllib3',
│ │ 'urllib3.packages', 'urllib3.packages.ssl_match_hostname',
│ │ - 'urllib3.packages.backports', 'urllib3.contrib',
│ │ - 'urllib3.contrib._securetransport', 'urllib3.util',
│ │ - ],
│ │ + 'urllib3.packages.backports', 'urllib3.packages.rfc3986',
│ │ + 'urllib3.contrib', 'urllib3.contrib._securetransport',
│ │ + 'urllib3.util'],
│ │ package_dir={'': 'src'},
│ │ requires=[],
│ │ python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4",
│ │ tests_require=[
│ │ # These are a less-specific subset of dev-requirements.txt, for the
│ │ # convenience of distro package maintainers.
│ │ 'pytest',
│ │ 'mock',
│ │ 'tornado',
│ │ ],
│ │ test_suite='test',
│ │ extras_require={
│ │ + 'brotli': [
│ │ + 'brotlipy>=0.6.0',
│ │ + ],
│ │ 'secure': [
│ │ - 'pyOpenSSL >= 0.14',
│ │ + 'pyOpenSSL>=0.14',
│ │ 'cryptography>=1.3.4',
│ │ 'idna>=2.0.0',
│ │ 'certifi',
│ │ - "ipaddress",
│ │ + "ipaddress; python_version=='2.7'",
│ │ ],
│ │ 'socks': [
│ │ 'PySocks>=1.5.6,<2.0,!=1.5.7',
│ │ ]
│ │ },
│ │ )
│ --- urllib3-1.24.1/test/test_retry.py
├── +++ urllib3-1.25.3/test/test_retry.py
│┄ Files similar despite different names (difference score: 2)
│ │ @@ -249,13 +249,13 @@
│ │ retry = Retry()
│ │ with pytest.raises(ReadTimeoutError):
│ │ retry.increment(method='POST', error=error)
│ │
│ │ def test_retry_default_remove_headers_on_redirect(self):
│ │ retry = Retry()
│ │
│ │ - assert list(retry.remove_headers_on_redirect) == ['Authorization']
│ │ + assert list(retry.remove_headers_on_redirect) == ['authorization']
│ │
│ │ def test_retry_set_remove_headers_on_redirect(self):
│ │ retry = Retry(remove_headers_on_redirect=['X-API-Secret'])
│ │
│ │ - assert list(retry.remove_headers_on_redirect) == ['X-API-Secret']
│ │ + assert list(retry.remove_headers_on_redirect) == ['x-api-secret']
│ --- urllib3-1.24.1/src/urllib3/_collections.py
├── +++ urllib3-1.25.3/src/urllib3/_collections.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/contrib/test_socks.py
├── +++ urllib3-1.25.3/test/contrib/test_socks.py
│┄ Files similar despite different names (difference score: 2)
│ │ @@ -1,14 +1,14 @@
│ │ import threading
│ │ import socket
│ │
│ │ from urllib3.contrib import socks
│ │ from urllib3.exceptions import ConnectTimeoutError, NewConnectionError
│ │
│ │ -from dummyserver.server import DEFAULT_CERTS
│ │ +from dummyserver.server import DEFAULT_CERTS, DEFAULT_CA
│ │ from dummyserver.testcase import IPV4SocketDummyServerTestCase
│ │
│ │ import pytest
│ │
│ │ try:
│ │ import ssl
│ │ from urllib3.util import ssl_ as better_ssl
│ │ @@ -711,14 +711,14 @@
│ │ b'Content-Length: 0\r\n'
│ │ b'\r\n')
│ │ tls.close()
│ │ sock.close()
│ │
│ │ self._start_server(request_handler)
│ │ proxy_url = "socks5h://%s:%s" % (self.host, self.port)
│ │ - pm = socks.SOCKSProxyManager(proxy_url)
│ │ + pm = socks.SOCKSProxyManager(proxy_url, ca_certs=DEFAULT_CA)
│ │ self.addCleanup(pm.clear)
│ │ response = pm.request('GET', 'https://localhost')
│ │
│ │ self.assertEqual(response.status, 200)
│ │ self.assertEqual(response.data, b'')
│ │ self.assertEqual(response.headers['Server'], 'SocksTestServer')
│ --- urllib3-1.24.1/src/urllib3/util/retry.py
├── +++ urllib3-1.25.3/src/urllib3/util/retry.py
│┄ Files similar despite different names (difference score: 1)
│ │ @@ -175,15 +175,16 @@
│ │ self.status_forcelist = status_forcelist or set()
│ │ self.method_whitelist = method_whitelist
│ │ self.backoff_factor = backoff_factor
│ │ self.raise_on_redirect = raise_on_redirect
│ │ self.raise_on_status = raise_on_status
│ │ self.history = history or tuple()
│ │ self.respect_retry_after_header = respect_retry_after_header
│ │ - self.remove_headers_on_redirect = remove_headers_on_redirect
│ │ + self.remove_headers_on_redirect = frozenset([
│ │ + h.lower() for h in remove_headers_on_redirect])
│ │
│ │ def new(self, **kw):
│ │ params = dict(
│ │ total=self.total,
│ │ connect=self.connect, read=self.read, redirect=self.redirect, status=self.status,
│ │ method_whitelist=self.method_whitelist,
│ │ status_forcelist=self.status_forcelist,
│ --- urllib3-1.24.1/src/urllib3/contrib/_securetransport/low_level.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/_securetransport/low_level.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/docs/user-guide.rst
├── +++ urllib3-1.25.3/docs/user-guide.rst
│┄ Files similar despite different names (difference score: 14)
│ │ @@ -136,15 +136,15 @@
│ │ ... fields={'field': 'value'})
│ │ >>> json.loads(r.data.decode('utf-8'))['form']
│ │ {'field': 'value'}
│ │
│ │ JSON
│ │ ~~~~
│ │
│ │ -You can sent JSON a request by specifying the encoded data as the ``body``
│ │ +You can send a JSON request by specifying the encoded data as the ``body``
│ │ argument and setting the ``Content-Type`` header when calling
│ │ :meth:`~poolmanager.PoolManager.request`::
│ │
│ │ >>> import json
│ │ >>> data = {'attribute': 'value'}
│ │ >>> encoded_data = json.dumps(data).encode('utf-8')
│ │ >>> r = http.request(
│ │ @@ -198,19 +198,23 @@
│ │ b'...'
│ │
│ │ .. _ssl:
│ │
│ │ Certificate verification
│ │ ------------------------
│ │
│ │ -It is highly recommended to always use SSL certificate verification.
│ │ -**By default, urllib3 does not verify HTTPS requests**.
│ │ + .. note:: *New in version 1.25*
│ │
│ │ -In order to enable verification you will need a set of root certificates. The easiest
│ │ -and most reliable method is to use the `certifi <https://certifi.io/>`_ package which provides Mozilla's root certificate bundle::
│ │ + HTTPS connections are now verified by default (``cert_reqs = 'CERT_REQUIRED'``).
│ │ +
│ │ +While you can disable certification verification, it is highly recommend to leave it on.
│ │ +
│ │ +Unless otherwise specified urllib3 will try to load the default system certificate stores.
│ │ +The most reliable cross-platform method is to use the `certifi <https://certifi.io/>`_
│ │ +package which provides Mozilla's root certificate bundle::
│ │
│ │ pip install certifi
│ │
│ │ You can also install certifi along with urllib3 by using the ``secure``
│ │ extra::
│ │
│ │ pip install urllib3[secure]
│ --- urllib3-1.24.1/test/socketpair_helper.py
├── +++ urllib3-1.25.3/test/socketpair_helper.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/util/ssl_.py
├── +++ urllib3-1.25.3/src/urllib3/util/ssl_.py
│┄ Files similar despite different names (difference score: 24)
│ │ @@ -1,18 +1,19 @@
│ │ from __future__ import absolute_import
│ │ import errno
│ │ import warnings
│ │ import hmac
│ │ -import socket
│ │ +import re
│ │
│ │ from binascii import hexlify, unhexlify
│ │ from hashlib import md5, sha1, sha256
│ │
│ │ from ..exceptions import SSLError, InsecurePlatformWarning, SNIMissingWarning
│ │ from ..packages import six
│ │ +from ..packages.rfc3986 import abnf_regexp
│ │
│ │
│ │ SSLContext = None
│ │ HAS_SNI = False
│ │ IS_PYOPENSSL = False
│ │ IS_SECURETRANSPORT = False
│ │
│ │ @@ -36,88 +37,86 @@
│ │ result |= l ^ r
│ │ return result == 0
│ │
│ │
│ │ _const_compare_digest = getattr(hmac, 'compare_digest',
│ │ _const_compare_digest_backport)
│ │
│ │ +# Borrow rfc3986's regular expressions for IPv4
│ │ +# and IPv6 addresses for use in is_ipaddress()
│ │ +_IP_ADDRESS_REGEX = re.compile(
│ │ + r'^(?:%s|%s|%s)$' % (
│ │ + abnf_regexp.IPv4_RE,
│ │ + abnf_regexp.IPv6_RE,
│ │ + abnf_regexp.IPv6_ADDRZ_RFC4007_RE
│ │ + )
│ │ +)
│ │
│ │ try: # Test for SSL features
│ │ import ssl
│ │ - from ssl import wrap_socket, CERT_NONE, PROTOCOL_SSLv23
│ │ + from ssl import wrap_socket, CERT_REQUIRED
│ │ from ssl import HAS_SNI # Has SNI?
│ │ except ImportError:
│ │ pass
│ │
│ │ +try: # Platform-specific: Python 3.6
│ │ + from ssl import PROTOCOL_TLS
│ │ + PROTOCOL_SSLv23 = PROTOCOL_TLS
│ │ +except ImportError:
│ │ + try:
│ │ + from ssl import PROTOCOL_SSLv23 as PROTOCOL_TLS
│ │ + PROTOCOL_SSLv23 = PROTOCOL_TLS
│ │ + except ImportError:
│ │ + PROTOCOL_SSLv23 = PROTOCOL_TLS = 2
│ │ +
│ │
│ │ try:
│ │ from ssl import OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_COMPRESSION
│ │ except ImportError:
│ │ OP_NO_SSLv2, OP_NO_SSLv3 = 0x1000000, 0x2000000
│ │ OP_NO_COMPRESSION = 0x20000
│ │
│ │
│ │ -# Python 2.7 doesn't have inet_pton on non-Linux so we fallback on inet_aton in
│ │ -# those cases. This means that we can only detect IPv4 addresses in this case.
│ │ -if hasattr(socket, 'inet_pton'):
│ │ - inet_pton = socket.inet_pton
│ │ -else:
│ │ - # Maybe we can use ipaddress if the user has urllib3[secure]?
│ │ - try:
│ │ - import ipaddress
│ │ -
│ │ - def inet_pton(_, host):
│ │ - if isinstance(host, bytes):
│ │ - host = host.decode('ascii')
│ │ - return ipaddress.ip_address(host)
│ │ -
│ │ - except ImportError: # Platform-specific: Non-Linux
│ │ - def inet_pton(_, host):
│ │ - return socket.inet_aton(host)
│ │ -
│ │ -
│ │ # A secure default.
│ │ # Sources for more information on TLS ciphers:
│ │ #
│ │ # - https://wiki.mozilla.org/Security/Server_Side_TLS
│ │ # - https://www.ssllabs.com/projects/best-practices/index.html
│ │ # - https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
│ │ #
│ │ # The general intent is:
│ │ -# - Prefer TLS 1.3 cipher suites
│ │ # - prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE),
│ │ # - prefer ECDHE over DHE for better performance,
│ │ # - prefer any AES-GCM and ChaCha20 over any AES-CBC for better performance and
│ │ # security,
│ │ # - prefer AES-GCM over ChaCha20 because hardware-accelerated AES is common,
│ │ -# - disable NULL authentication, MD5 MACs and DSS for security reasons.
│ │ +# - disable NULL authentication, MD5 MACs, DSS, and other
│ │ +# insecure ciphers for security reasons.
│ │ +# - NOTE: TLS 1.3 cipher suites are managed through a different interface
│ │ +# not exposed by CPython (yet!) and are enabled by default if they're available.
│ │ DEFAULT_CIPHERS = ':'.join([
│ │ - 'TLS13-AES-256-GCM-SHA384',
│ │ - 'TLS13-CHACHA20-POLY1305-SHA256',
│ │ - 'TLS13-AES-128-GCM-SHA256',
│ │ + 'ECDHE+AESGCM',
│ │ + 'ECDHE+CHACHA20',
│ │ + 'DHE+AESGCM',
│ │ + 'DHE+CHACHA20',
│ │ 'ECDH+AESGCM',
│ │ - 'ECDH+CHACHA20',
│ │ 'DH+AESGCM',
│ │ - 'DH+CHACHA20',
│ │ - 'ECDH+AES256',
│ │ - 'DH+AES256',
│ │ - 'ECDH+AES128',
│ │ + 'ECDH+AES',
│ │ 'DH+AES',
│ │ 'RSA+AESGCM',
│ │ 'RSA+AES',
│ │ '!aNULL',
│ │ '!eNULL',
│ │ '!MD5',
│ │ + '!DSS',
│ │ ])
│ │
│ │ try:
│ │ from ssl import SSLContext # Modern SSL?
│ │ except ImportError:
│ │ - import sys
│ │ -
│ │ class SSLContext(object): # Platform-specific: Python 2
│ │ def __init__(self, protocol_version):
│ │ self.protocol = protocol_version
│ │ # Use default values from a real SSLContext
│ │ self.check_hostname = False
│ │ self.verify_mode = ssl.CERT_NONE
│ │ self.ca_certs = None
│ │ @@ -195,15 +194,15 @@
│ │ If given a string it is assumed to be the name of the constant in the
│ │ :mod:`ssl` module or its abbreviation.
│ │ (So you can specify `REQUIRED` instead of `CERT_REQUIRED`.
│ │ If it's neither `None` nor a string we assume it is already the numeric
│ │ constant which can directly be passed to wrap_socket.
│ │ """
│ │ if candidate is None:
│ │ - return CERT_NONE
│ │ + return CERT_REQUIRED
│ │
│ │ if isinstance(candidate, str):
│ │ res = getattr(ssl, candidate, None)
│ │ if res is None:
│ │ res = getattr(ssl, 'CERT_' + candidate)
│ │ return res
│ │
│ │ @@ -211,15 +210,15 @@
│ │
│ │
│ │ def resolve_ssl_version(candidate):
│ │ """
│ │ like resolve_cert_reqs
│ │ """
│ │ if candidate is None:
│ │ - return PROTOCOL_SSLv23
│ │ + return PROTOCOL_TLS
│ │
│ │ if isinstance(candidate, str):
│ │ res = getattr(ssl, candidate, None)
│ │ if res is None:
│ │ res = getattr(ssl, 'PROTOCOL_' + candidate)
│ │ return res
│ │
│ │ @@ -257,15 +256,15 @@
│ │ ``ssl.OP_NO_SSLv3``, ``ssl.OP_NO_COMPRESSION``.
│ │ :param ciphers:
│ │ Which cipher suites to allow the server to select.
│ │ :returns:
│ │ Constructed SSLContext object with specified options
│ │ :rtype: SSLContext
│ │ """
│ │ - context = SSLContext(ssl_version or ssl.PROTOCOL_SSLv23)
│ │ + context = SSLContext(ssl_version or PROTOCOL_TLS)
│ │
│ │ context.set_ciphers(ciphers or DEFAULT_CIPHERS)
│ │
│ │ # Setting the default here, as we may have no ssl module on import
│ │ cert_reqs = ssl.CERT_REQUIRED if cert_reqs is None else cert_reqs
│ │
│ │ if options is None:
│ │ @@ -287,15 +286,15 @@
│ │ context.check_hostname = False
│ │ return context
│ │
│ │
│ │ def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
│ │ ca_certs=None, server_hostname=None,
│ │ ssl_version=None, ciphers=None, ssl_context=None,
│ │ - ca_cert_dir=None):
│ │ + ca_cert_dir=None, key_password=None):
│ │ """
│ │ All arguments except for server_hostname, ssl_context, and ca_cert_dir have
│ │ the same meaning as they do when using :func:`ssl.wrap_socket`.
│ │
│ │ :param server_hostname:
│ │ When SNI is supported, the expected hostname of the certificate
│ │ :param ssl_context:
│ │ @@ -303,14 +302,16 @@
│ │ be created using :func:`create_urllib3_context`.
│ │ :param ciphers:
│ │ A string of ciphers we wish the client to support.
│ │ :param ca_cert_dir:
│ │ A directory containing CA certificates in multiple separate files, as
│ │ supported by OpenSSL's -CApath flag or the capath argument to
│ │ SSLContext.load_verify_locations().
│ │ + :param key_password:
│ │ + Optional password if the keyfile is encrypted.
│ │ """
│ │ context = ssl_context
│ │ if context is None:
│ │ # Note: This branch of code and all the variables in it are no longer
│ │ # used by urllib3 itself. We should consider deprecating and removing
│ │ # this code.
│ │ context = create_urllib3_context(ssl_version, cert_reqs,
│ │ @@ -323,20 +324,30 @@
│ │ raise SSLError(e)
│ │ # Py33 raises FileNotFoundError which subclasses OSError
│ │ # These are not equivalent unless we check the errno attribute
│ │ except OSError as e: # Platform-specific: Python 3.3 and beyond
│ │ if e.errno == errno.ENOENT:
│ │ raise SSLError(e)
│ │ raise
│ │ - elif getattr(context, 'load_default_certs', None) is not None:
│ │ +
│ │ + elif ssl_context is None and hasattr(context, 'load_default_certs'):
│ │ # try to load OS default certs; works well on Windows (require Python3.4+)
│ │ context.load_default_certs()
│ │
│ │ + # Attempt to detect if we get the goofy behavior of the
│ │ + # keyfile being encrypted and OpenSSL asking for the
│ │ + # passphrase via the terminal and instead error out.
│ │ + if keyfile and key_password is None and _is_key_file_encrypted(keyfile):
│ │ + raise SSLError("Client private key is encrypted, password is required")
│ │ +
│ │ if certfile:
│ │ - context.load_cert_chain(certfile, keyfile)
│ │ + if key_password is None:
│ │ + context.load_cert_chain(certfile, keyfile)
│ │ + else:
│ │ + context.load_cert_chain(certfile, keyfile, key_password)
│ │
│ │ # If we detect server_hostname is an IP address then the SNI
│ │ # extension should not be used according to RFC3546 Section 3.1
│ │ # We shouldn't warn the user if SNI isn't available but we would
│ │ # not be using SNI anyways due to IP address for server_hostname.
│ │ if ((server_hostname is not None and not is_ipaddress(server_hostname))
│ │ or IS_SECURETRANSPORT):
│ │ @@ -354,28 +365,28 @@
│ │ SNIMissingWarning
│ │ )
│ │
│ │ return context.wrap_socket(sock)
│ │
│ │
│ │ def is_ipaddress(hostname):
│ │ - """Detects whether the hostname given is an IP address.
│ │ + """Detects whether the hostname given is an IPv4 or IPv6 address.
│ │ + Also detects IPv6 addresses with Zone IDs.
│ │
│ │ :param str hostname: Hostname to examine.
│ │ :return: True if the hostname is an IP address, False otherwise.
│ │ """
│ │ if six.PY3 and isinstance(hostname, bytes):
│ │ # IDN A-label bytes are ASCII compatible.
│ │ hostname = hostname.decode('ascii')
│ │ + return _IP_ADDRESS_REGEX.match(hostname) is not None
│ │
│ │ - families = [socket.AF_INET]
│ │ - if hasattr(socket, 'AF_INET6'):
│ │ - families.append(socket.AF_INET6)
│ │
│ │ - for af in families:
│ │ - try:
│ │ - inet_pton(af, hostname)
│ │ - except (socket.error, ValueError, OSError):
│ │ - pass
│ │ - else:
│ │ - return True
│ │ +def _is_key_file_encrypted(key_file):
│ │ + """Detects if a key file is encrypted or not."""
│ │ + with open(key_file, 'r') as f:
│ │ + for line in f:
│ │ + # Look for Proc-Type: 4,ENCRYPTED
│ │ + if 'ENCRYPTED' in line:
│ │ + return True
│ │ +
│ │ return False
│ --- urllib3-1.24.1/src/urllib3/util/__init__.py
├── +++ urllib3-1.25.3/src/urllib3/util/__init__.py
│┄ Files similar despite different names (difference score: 52)
│ │ @@ -8,14 +8,15 @@
│ │ HAS_SNI,
│ │ IS_PYOPENSSL,
│ │ IS_SECURETRANSPORT,
│ │ assert_fingerprint,
│ │ resolve_cert_reqs,
│ │ resolve_ssl_version,
│ │ ssl_wrap_socket,
│ │ + PROTOCOL_TLS,
│ │ )
│ │ from .timeout import (
│ │ current_time,
│ │ Timeout,
│ │ )
│ │
│ │ from .retry import Retry
│ │ @@ -31,14 +32,15 @@
│ │ )
│ │
│ │ __all__ = (
│ │ 'HAS_SNI',
│ │ 'IS_PYOPENSSL',
│ │ 'IS_SECURETRANSPORT',
│ │ 'SSLContext',
│ │ + 'PROTOCOL_TLS',
│ │ 'Retry',
│ │ 'Timeout',
│ │ 'Url',
│ │ 'assert_fingerprint',
│ │ 'current_time',
│ │ 'is_connection_dropped',
│ │ 'is_fp_closed',
│ --- urllib3-1.24.1/src/urllib3/util/request.py
├── +++ urllib3-1.25.3/src/urllib3/util/request.py
│┄ Files similar despite different names (difference score: 14)
│ │ @@ -1,14 +1,21 @@
│ │ from __future__ import absolute_import
│ │ from base64 import b64encode
│ │
│ │ from ..packages.six import b, integer_types
│ │ from ..exceptions import UnrewindableBodyError
│ │
│ │ ACCEPT_ENCODING = 'gzip,deflate'
│ │ +try:
│ │ + import brotli as _unused_module_brotli # noqa: F401
│ │ +except ImportError:
│ │ + pass
│ │ +else:
│ │ + ACCEPT_ENCODING += ',br'
│ │ +
│ │ _FAILEDTELL = object()
│ │
│ │
│ │ def make_headers(keep_alive=None, accept_encoding=None, user_agent=None,
│ │ basic_auth=None, proxy_basic_auth=None, disable_cache=None):
│ │ """
│ │ Shortcuts for generating request headers.
│ --- urllib3-1.24.1/src/urllib3/packages/six.py
├── +++ urllib3-1.25.3/src/urllib3/packages/six.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/client.csr
├── +++ urllib3-1.25.3/dummyserver/certs/client.csr
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/server.py
├── +++ urllib3-1.25.3/dummyserver/server.py
│┄ Files similar despite different names (difference score: 13)
│ │ @@ -42,31 +42,38 @@
│ │ commonName=u'SnakeOilClient',
│ │ emailAddress=u'[email protected]'),
│ │ }
│ │ DEFAULT_CLIENT_NO_INTERMEDIATE_CERTS = {
│ │ 'certfile': os.path.join(CERTS_PATH, 'client_no_intermediate.pem'),
│ │ 'keyfile': os.path.join(CERTS_PATH, 'client_intermediate.key'),
│ │ }
│ │ +PASSWORD_KEYFILE = os.path.join(CERTS_PATH, 'server_password.key')
│ │ +PASSWORD_CLIENT_KEYFILE = os.path.join(CERTS_PATH, 'client_password.key')
│ │ NO_SAN_CERTS = {
│ │ 'certfile': os.path.join(CERTS_PATH, 'server.no_san.crt'),
│ │ 'keyfile': DEFAULT_CERTS['keyfile']
│ │ }
│ │ IP_SAN_CERTS = {
│ │ 'certfile': os.path.join(CERTS_PATH, 'server.ip_san.crt'),
│ │ 'keyfile': DEFAULT_CERTS['keyfile']
│ │ }
│ │ IPV6_ADDR_CERTS = {
│ │ 'certfile': os.path.join(CERTS_PATH, 'server.ipv6addr.crt'),
│ │ 'keyfile': os.path.join(CERTS_PATH, 'server.ipv6addr.key'),
│ │ }
│ │ +IPV6_SAN_CERTS = {
│ │ + 'certfile': os.path.join(CERTS_PATH, 'server.ipv6_san.crt'),
│ │ + 'keyfile': DEFAULT_CERTS['keyfile']
│ │ +}
│ │ DEFAULT_CA = os.path.join(CERTS_PATH, 'cacert.pem')
│ │ DEFAULT_CA_BAD = os.path.join(CERTS_PATH, 'client_bad.pem')
│ │ NO_SAN_CA = os.path.join(CERTS_PATH, 'cacert.no_san.pem')
│ │ DEFAULT_CA_DIR = os.path.join(CERTS_PATH, 'ca_path_test')
│ │ IPV6_ADDR_CA = os.path.join(CERTS_PATH, 'server.ipv6addr.crt')
│ │ +IPV6_SAN_CA = os.path.join(CERTS_PATH, 'server.ipv6_san.crt')
│ │ COMBINED_CERT_AND_KEY = os.path.join(CERTS_PATH, 'server.combined.pem')
│ │
│ │
│ │ def _has_ipv6(host):
│ │ """ Returns True if the system can bind an IPv6 address. """
│ │ sock = None
│ │ has_ipv6 = False
│ --- urllib3-1.24.1/test/test_filepost.py
├── +++ urllib3-1.25.3/test/test_filepost.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/with_dummyserver/test_socketlevel.py
├── +++ urllib3-1.25.3/test/with_dummyserver/test_socketlevel.py
│┄ Files similar despite different names (difference score: 19)
│ │ @@ -8,37 +8,43 @@
│ │ ProxyError,
│ │ ReadTimeoutError,
│ │ SSLError,
│ │ ProtocolError,
│ │ )
│ │ from urllib3.response import httplib
│ │ from urllib3.util.ssl_ import HAS_SNI
│ │ +from urllib3.util import ssl_
│ │ from urllib3.util.timeout import Timeout
│ │ from urllib3.util.retry import Retry
│ │ from urllib3._collections import HTTPHeaderDict
│ │
│ │ from dummyserver.testcase import SocketDummyServerTestCase, consume_socket
│ │ from dummyserver.server import (
│ │ - DEFAULT_CERTS, DEFAULT_CA, COMBINED_CERT_AND_KEY, get_unreachable_address)
│ │ + DEFAULT_CERTS, DEFAULT_CA, COMBINED_CERT_AND_KEY,
│ │ + PASSWORD_KEYFILE, get_unreachable_address
│ │ +)
│ │
│ │ from .. import onlyPy3, LogRecorder
│ │
│ │ try:
│ │ from mimetools import Message as MimeToolMessage
│ │ except ImportError:
│ │ class MimeToolMessage(object):
│ │ pass
│ │ from collections import OrderedDict
│ │ from threading import Event
│ │ import select
│ │ import socket
│ │ import ssl
│ │ +import mock
│ │
│ │ import pytest
│ │
│ │ +from test import fails_on_travis_gce, requires_ssl_context_keyfile_password
│ │ +
│ │
│ │ class TestCookies(SocketDummyServerTestCase):
│ │
│ │ def test_multi_setcookie(self):
│ │ def multicookie_response_handler(listener):
│ │ sock = listener.accept()[0]
│ │
│ │ @@ -225,14 +231,88 @@
│ │ else:
│ │ done_receiving.set()
│ │ self.fail(
│ │ "Expected server to reject connection due to missing client "
│ │ "certificates"
│ │ )
│ │
│ │ + @requires_ssl_context_keyfile_password
│ │ + def test_client_cert_with_string_password(self):
│ │ + self.run_client_cert_with_password_test(u"letmein")
│ │ +
│ │ + @requires_ssl_context_keyfile_password
│ │ + def test_client_cert_with_bytes_password(self):
│ │ + self.run_client_cert_with_password_test(b"letmein")
│ │ +
│ │ + def run_client_cert_with_password_test(self, password):
│ │ + """
│ │ + Tests client certificate password functionality
│ │ + """
│ │ + done_receiving = Event()
│ │ + client_certs = []
│ │ +
│ │ + def socket_handler(listener):
│ │ + sock = listener.accept()[0]
│ │ + sock = self._wrap_in_ssl(sock)
│ │ +
│ │ + client_certs.append(sock.getpeercert())
│ │ +
│ │ + data = b''
│ │ + while not data.endswith(b'\r\n\r\n'):
│ │ + data += sock.recv(8192)
│ │ +
│ │ + sock.sendall(
│ │ + b'HTTP/1.1 200 OK\r\n'
│ │ + b'Server: testsocket\r\n'
│ │ + b'Connection: close\r\n'
│ │ + b'Content-Length: 6\r\n'
│ │ + b'\r\n'
│ │ + b'Valid!'
│ │ + )
│ │ +
│ │ + done_receiving.wait(5)
│ │ + sock.close()
│ │ +
│ │ + self._start_server(socket_handler)
│ │ + ssl_context = ssl_.SSLContext(ssl_.PROTOCOL_SSLv23)
│ │ + ssl_context.load_cert_chain(
│ │ + certfile=DEFAULT_CERTS['certfile'],
│ │ + keyfile=PASSWORD_KEYFILE,
│ │ + password=password
│ │ + )
│ │ +
│ │ + pool = HTTPSConnectionPool(
│ │ + self.host,
│ │ + self.port,
│ │ + ssl_context=ssl_context,
│ │ + cert_reqs='REQUIRED',
│ │ + ca_certs=DEFAULT_CA,
│ │ + )
│ │ + self.addCleanup(pool.close)
│ │ + pool.request('GET', '/', retries=0)
│ │ + done_receiving.set()
│ │ +
│ │ + self.assertEqual(len(client_certs), 1)
│ │ +
│ │ + @requires_ssl_context_keyfile_password
│ │ + def test_load_keyfile_with_invalid_password(self):
│ │ + context = ssl_.SSLContext(ssl_.PROTOCOL_SSLv23)
│ │ +
│ │ + # Different error is raised depending on context.
│ │ + if ssl_.IS_PYOPENSSL:
│ │ + from OpenSSL.SSL import Error
│ │ + expected_error = Error
│ │ + else:
│ │ + expected_error = ssl.SSLError
│ │ +
│ │ + with pytest.raises(expected_error):
│ │ + context.load_cert_chain(certfile=DEFAULT_CERTS["certfile"],
│ │ + keyfile=PASSWORD_KEYFILE,
│ │ + password=b'letmei')
│ │ +
│ │
│ │ class TestSocketClosing(SocketDummyServerTestCase):
│ │
│ │ def test_recovery_when_server_closes_connection(self):
│ │ # Does the pool work seamlessly if an open connection in the
│ │ # connection pool gets hung up on by the server, then reaches
│ │ # the front of the queue again?
│ │ @@ -288,15 +368,15 @@
│ │ pass
│ │
│ │ timed_out.wait()
│ │ sock.close()
│ │
│ │ self._start_server(socket_handler)
│ │ http = HTTPConnectionPool(self.host, self.port,
│ │ - timeout=0.001,
│ │ + timeout=0.01,
│ │ retries=False,
│ │ maxsize=3,
│ │ block=True)
│ │ self.addCleanup(http.close)
│ │
│ │ try:
│ │ self.assertRaises(ReadTimeoutError, http.request, 'GET', '/', release_conn=False)
│ │ @@ -311,15 +391,15 @@
│ │ def socket_handler(listener):
│ │ sock = listener.accept()[0]
│ │ sock.recv(65536)
│ │ timed_out.wait()
│ │ sock.close()
│ │
│ │ self._start_server(socket_handler)
│ │ - pool = HTTPConnectionPool(self.host, self.port, timeout=0.001, retries=True)
│ │ + pool = HTTPConnectionPool(self.host, self.port, timeout=0.01, retries=True)
│ │ self.addCleanup(pool.close)
│ │
│ │ try:
│ │ self.assertRaises(ReadTimeoutError, pool.request, 'POST', '/')
│ │ finally:
│ │ timed_out.set()
│ │
│ │ @@ -332,15 +412,15 @@
│ │ while not sock.recv(65536):
│ │ pass
│ │
│ │ timed_out.wait()
│ │ sock.close()
│ │
│ │ self._start_server(socket_handler)
│ │ - pool = HTTPSConnectionPool(self.host, self.port, timeout=0.001, retries=False)
│ │ + pool = HTTPSConnectionPool(self.host, self.port, timeout=0.01, retries=False)
│ │ self.addCleanup(pool.close)
│ │ try:
│ │ self.assertRaises(ReadTimeoutError, pool.request, 'GET', '/')
│ │ finally:
│ │ timed_out.set()
│ │
│ │ def test_timeout_errors_cause_retries(self):
│ │ @@ -371,15 +451,15 @@
│ │ # out within 1 second. This should be long enough for any socket
│ │ # operations in the test suite to complete
│ │ default_timeout = socket.getdefaulttimeout()
│ │ socket.setdefaulttimeout(1)
│ │
│ │ try:
│ │ self._start_server(socket_handler)
│ │ - t = Timeout(connect=0.001, read=0.001)
│ │ + t = Timeout(connect=0.001, read=0.01)
│ │ pool = HTTPConnectionPool(self.host, self.port, timeout=t)
│ │ self.addCleanup(pool.close)
│ │
│ │ response = pool.request('GET', '/', retries=1)
│ │ self.assertEqual(response.status, 200)
│ │ self.assertEqual(response.data, b'Response 2')
│ │ finally:
│ │ @@ -404,15 +484,15 @@
│ │ sock.close()
│ │
│ │ self._start_server(socket_handler)
│ │ pool = HTTPConnectionPool(self.host, self.port)
│ │ self.addCleanup(pool.close)
│ │
│ │ response = pool.urlopen('GET', '/', retries=0, preload_content=False,
│ │ - timeout=Timeout(connect=1, read=0.001))
│ │ + timeout=Timeout(connect=1, read=0.01))
│ │ try:
│ │ self.assertRaises(ReadTimeoutError, response.read)
│ │ finally:
│ │ timed_out.set()
│ │
│ │ def test_delayed_body_read_timeout_with_preload(self):
│ │ timed_out = Event()
│ │ @@ -434,15 +514,15 @@
│ │ self._start_server(socket_handler)
│ │ pool = HTTPConnectionPool(self.host, self.port)
│ │ self.addCleanup(pool.close)
│ │
│ │ try:
│ │ self.assertRaises(ReadTimeoutError, pool.urlopen,
│ │ 'GET', '/', retries=False,
│ │ - timeout=Timeout(connect=1, read=0.001))
│ │ + timeout=Timeout(connect=1, read=0.01))
│ │ finally:
│ │ timed_out.set()
│ │
│ │ def test_incomplete_response(self):
│ │ body = 'Response'
│ │ partial_body = body[:2]
│ │
│ │ @@ -531,15 +611,15 @@
│ │ timed_out.wait()
│ │ sock.close()
│ │
│ │ self._start_server(socket_handler)
│ │ with HTTPConnectionPool(self.host, self.port) as pool:
│ │ poolsize = pool.pool.qsize()
│ │ response = pool.urlopen('GET', '/', retries=0, preload_content=False,
│ │ - timeout=Timeout(connect=1, read=0.001))
│ │ + timeout=Timeout(connect=1, read=0.01))
│ │ try:
│ │ self.assertRaises(ReadTimeoutError, response.read)
│ │ self.assertEqual(poolsize, pool.pool.qsize())
│ │ finally:
│ │ timed_out.set()
│ │
│ │ def test_connection_cleanup_on_protocol_error_during_read(self):
│ │ @@ -620,24 +700,24 @@
│ │ sock.close()
│ │
│ │ self._start_server(socket_handler)
│ │ with HTTPConnectionPool(self.host, self.port) as pool:
│ │ # First request should fail.
│ │ response = pool.urlopen('GET', '/', retries=0,
│ │ preload_content=False,
│ │ - timeout=Timeout(connect=1, read=0.001))
│ │ + timeout=Timeout(connect=1, read=0.1))
│ │ try:
│ │ self.assertRaises(ReadTimeoutError, response.read)
│ │ finally:
│ │ timed_out.set()
│ │
│ │ # Second should succeed.
│ │ response = pool.urlopen('GET', '/', retries=0,
│ │ preload_content=False,
│ │ - timeout=Timeout(connect=1, read=0.1))
│ │ + timeout=Timeout(connect=1, read=1))
│ │ self.assertEqual(len(response.read()), 8)
│ │
│ │ def test_closing_response_actually_closes_connection(self):
│ │ done_closing = Event()
│ │ complete = Event()
│ │
│ │ def socket_handler(listener):
│ │ @@ -720,15 +800,15 @@
│ │
│ │ self._start_server(socket_handler)
│ │ with HTTPConnectionPool(self.host, self.port, maxsize=1) as pool:
│ │ # First request should fail, but the timeout and `retries=1` should
│ │ # save it.
│ │ response = pool.urlopen('GET', '/', retries=1,
│ │ release_conn=False, preload_content=False,
│ │ - timeout=Timeout(connect=1, read=0.001))
│ │ + timeout=Timeout(connect=1, read=0.01))
│ │
│ │ # The connection should still be on the response object, and none
│ │ # should be in the pool. We opened two though.
│ │ self.assertEqual(pool.num_connections, 2)
│ │ self.assertEqual(pool.pool.qsize(), 0)
│ │ self.assertIsNotNone(response.connection)
│ │
│ │ @@ -889,15 +969,15 @@
│ │ def echo_socket_handler(listener):
│ │ proxy_ssl_one(listener)
│ │ proxy_ssl_one(listener)
│ │
│ │ self._start_server(echo_socket_handler)
│ │ base_url = 'http://%s:%d' % (self.host, self.port)
│ │
│ │ - proxy = proxy_from_url(base_url)
│ │ + proxy = proxy_from_url(base_url, ca_certs=DEFAULT_CA)
│ │ self.addCleanup(proxy.clear)
│ │
│ │ url = 'https://{0}'.format(self.host)
│ │ conn = proxy.connection_from_url(url)
│ │ r = conn.urlopen('GET', url, retries=0)
│ │ self.assertEqual(r.status, 200)
│ │ r = conn.urlopen('GET', url, retries=0)
│ │ @@ -933,15 +1013,15 @@
│ │ ssl_sock.close()
│ │ else:
│ │ sock.close()
│ │
│ │ self._start_server(echo_socket_handler)
│ │ base_url = 'http://%s:%d' % (self.host, self.port)
│ │
│ │ - proxy = proxy_from_url(base_url)
│ │ + proxy = proxy_from_url(base_url, cert_reqs='NONE')
│ │ self.addCleanup(proxy.clear)
│ │
│ │ url = 'https://[{0}]'.format(ipv6_addr)
│ │ conn = proxy.connection_from_url(url)
│ │ try:
│ │ r = conn.urlopen('GET', url, retries=0)
│ │ self.assertEqual(r.status, 200)
│ │ @@ -987,16 +1067,15 @@
│ │ timed_out = Event()
│ │
│ │ def socket_handler(listener):
│ │ sock = listener.accept()[0]
│ │ ssl_sock = ssl.wrap_socket(sock,
│ │ server_side=True,
│ │ keyfile=DEFAULT_CERTS['keyfile'],
│ │ - certfile=DEFAULT_CERTS['certfile'],
│ │ - ca_certs=DEFAULT_CA)
│ │ + certfile=DEFAULT_CERTS['certfile'])
│ │
│ │ buf = b''
│ │ while not buf.endswith(b'\r\n\r\n'):
│ │ buf += ssl_sock.recv(65536)
│ │
│ │ # Send incomplete message (note Content-Length)
│ │ ssl_sock.send((
│ │ @@ -1007,19 +1086,19 @@
│ │ 'Hi-').encode('utf-8'))
│ │ timed_out.wait()
│ │
│ │ sock.close()
│ │ ssl_sock.close()
│ │
│ │ self._start_server(socket_handler)
│ │ - pool = HTTPSConnectionPool(self.host, self.port)
│ │ + pool = HTTPSConnectionPool(self.host, self.port, ca_certs=DEFAULT_CA)
│ │ self.addCleanup(pool.close)
│ │
│ │ response = pool.urlopen('GET', '/', retries=0, preload_content=False,
│ │ - timeout=Timeout(connect=1, read=0.001))
│ │ + timeout=Timeout(connect=1, read=0.01))
│ │ try:
│ │ self.assertRaises(ReadTimeoutError, response.read)
│ │ finally:
│ │ timed_out.set()
│ │
│ │ def test_ssl_failed_fingerprint_verification(self):
│ │ def socket_handler(listener):
│ │ @@ -1045,15 +1124,15 @@
│ │ ':9A:8C:B6:07:CA:58:EE:74:5E')
│ │
│ │ def request():
│ │ pool = HTTPSConnectionPool(self.host, self.port,
│ │ assert_fingerprint=fingerprint)
│ │ try:
│ │ response = pool.urlopen('GET', '/', preload_content=False,
│ │ - timeout=Timeout(connect=1, read=0.001),
│ │ + timeout=Timeout(connect=1, read=0.01),
│ │ retries=0)
│ │ response.read()
│ │ finally:
│ │ pool.close()
│ │
│ │ with self.assertRaises(MaxRetryError) as cm:
│ │ request()
│ │ @@ -1097,19 +1176,96 @@
│ │ b'Content-Type: text/plain\r\n'
│ │ b'Content-Length: 7\r\n\r\n'
│ │ b'Success')
│ │ ssl_sock.close()
│ │
│ │ self._start_server(socket_handler)
│ │
│ │ - pool = HTTPSConnectionPool(self.host, self.port)
│ │ + pool = HTTPSConnectionPool(self.host, self.port, ca_certs=DEFAULT_CA)
│ │ self.addCleanup(pool.close)
│ │ response = pool.urlopen('GET', '/', retries=1)
│ │ self.assertEqual(response.data, b'Success')
│ │
│ │ + def test_ssl_load_default_certs_when_empty(self):
│ │ + def socket_handler(listener):
│ │ + sock = listener.accept()[0]
│ │ + ssl_sock = ssl.wrap_socket(sock,
│ │ + server_side=True,
│ │ + keyfile=DEFAULT_CERTS['keyfile'],
│ │ + certfile=DEFAULT_CERTS['certfile'],
│ │ + ca_certs=DEFAULT_CA)
│ │ +
│ │ + buf = b''
│ │ + while not buf.endswith(b'\r\n\r\n'):
│ │ + buf += ssl_sock.recv(65536)
│ │ +
│ │ + ssl_sock.send(b'HTTP/1.1 200 OK\r\n'
│ │ + b'Content-Type: text/plain\r\n'
│ │ + b'Content-Length: 5\r\n\r\n'
│ │ + b'Hello')
│ │ +
│ │ + ssl_sock.close()
│ │ + sock.close()
│ │ +
│ │ + context = mock.create_autospec(ssl_.SSLContext)
│ │ + context.load_default_certs = mock.Mock()
│ │ + context.options = 0
│ │ +
│ │ + with mock.patch("urllib3.util.ssl_.SSLContext", lambda *_, **__: context):
│ │ +
│ │ + self._start_server(socket_handler)
│ │ + pool = HTTPSConnectionPool(self.host, self.port)
│ │ + self.addCleanup(pool.close)
│ │ +
│ │ + with self.assertRaises(MaxRetryError):
│ │ + pool.request("GET", "/", timeout=0.01)
│ │ +
│ │ + context.load_default_certs.assert_called_with()
│ │ +
│ │ + def test_ssl_dont_load_default_certs_when_given(self):
│ │ + def socket_handler(listener):
│ │ + sock = listener.accept()[0]
│ │ + ssl_sock = ssl.wrap_socket(sock,
│ │ + server_side=True,
│ │ + keyfile=DEFAULT_CERTS['keyfile'],
│ │ + certfile=DEFAULT_CERTS['certfile'],
│ │ + ca_certs=DEFAULT_CA)
│ │ +
│ │ + buf = b''
│ │ + while not buf.endswith(b'\r\n\r\n'):
│ │ + buf += ssl_sock.recv(65536)
│ │ +
│ │ + ssl_sock.send(b'HTTP/1.1 200 OK\r\n'
│ │ + b'Content-Type: text/plain\r\n'
│ │ + b'Content-Length: 5\r\n\r\n'
│ │ + b'Hello')
│ │ +
│ │ + ssl_sock.close()
│ │ + sock.close()
│ │ +
│ │ + context = mock.create_autospec(ssl_.SSLContext)
│ │ + context.load_default_certs = mock.Mock()
│ │ + context.options = 0
│ │ +
│ │ + with mock.patch("urllib3.util.ssl_.SSLContext", lambda *_, **__: context):
│ │ + for kwargs in [{"ca_certs": "/a"},
│ │ + {"ca_cert_dir": "/a"},
│ │ + {"ca_certs": "a", "ca_cert_dir": "a"},
│ │ + {"ssl_context": context}]:
│ │ +
│ │ + self._start_server(socket_handler)
│ │ +
│ │ + pool = HTTPSConnectionPool(self.host, self.port, **kwargs)
│ │ + self.addCleanup(pool.close)
│ │ +
│ │ + with self.assertRaises(MaxRetryError):
│ │ + pool.request("GET", "/", timeout=0.01)
│ │ +
│ │ + context.load_default_certs.assert_not_called()
│ │ +
│ │
│ │ class TestErrorWrapping(SocketDummyServerTestCase):
│ │
│ │ def test_bad_statusline(self):
│ │ self.start_response_handler(
│ │ b'HTTP/1.1 Omg What Is This?\r\n'
│ │ b'Content-Length: 0\r\n'
│ │ @@ -1214,14 +1370,15 @@
│ │ self._start_server(socket_handler)
│ │
│ │ pool = HTTPConnectionPool(self.host, self.port, retries=False)
│ │ self.addCleanup(pool.close)
│ │ pool.request('GET', '/', headers=OrderedDict(expected_request_headers))
│ │ self.assertEqual(expected_request_headers, actual_request_headers)
│ │
│ │ + @fails_on_travis_gce
│ │ def test_request_host_header_ignores_fqdn_dot(self):
│ │
│ │ received_headers = []
│ │
│ │ def socket_handler(listener):
│ │ sock = listener.accept()[0]
│ --- urllib3-1.24.1/test/test_response.py
├── +++ urllib3-1.25.3/test/test_response.py
│┄ Files similar despite different names (difference score: 4)
│ │ @@ -2,22 +2,24 @@
│ │ import zlib
│ │
│ │ from io import BytesIO, BufferedReader
│ │
│ │ import pytest
│ │ import mock
│ │
│ │ -from urllib3.response import HTTPResponse
│ │ +from urllib3.response import HTTPResponse, brotli
│ │ from urllib3.exceptions import (
│ │ DecodeError, ResponseNotChunked, ProtocolError, InvalidHeader
│ │ )
│ │ from urllib3.packages.six.moves import http_client as httplib
│ │ from urllib3.util.retry import Retry, RequestHistory
│ │ from urllib3.util.response import is_fp_closed
│ │
│ │ +from test import onlyBrotlipy
│ │ +
│ │ from base64 import b64decode
│ │
│ │ # A known random (i.e, not-too-compressible) payload generated with:
│ │ # "".join(random.choice(string.printable) for i in xrange(512))
│ │ # .encode("zlib").encode("base64")
│ │ # Randomness in tests == bad, and fixing a seed may not be sufficient.
│ │ ZLIB_PAYLOAD = b64decode(b"""\
│ │ @@ -204,14 +206,43 @@
│ │ data = data * 3 + b'foo'
│ │
│ │ fp = BytesIO(data)
│ │ r = HTTPResponse(fp, headers={'content-encoding': 'gzip'})
│ │
│ │ assert r.data == b'foofoofoo'
│ │
│ │ + @onlyBrotlipy()
│ │ + def test_decode_brotli(self):
│ │ + data = brotli.compress(b'foo')
│ │ +
│ │ + fp = BytesIO(data)
│ │ + r = HTTPResponse(fp, headers={'content-encoding': 'br'})
│ │ + assert r.data == b'foo'
│ │ +
│ │ + @onlyBrotlipy()
│ │ + def test_chunked_decoding_brotli(self):
│ │ + data = brotli.compress(b'foobarbaz')
│ │ +
│ │ + fp = BytesIO(data)
│ │ + r = HTTPResponse(
│ │ + fp, headers={'content-encoding': 'br'}, preload_content=False)
│ │ +
│ │ + ret = b''
│ │ + for _ in range(100):
│ │ + ret += r.read(1)
│ │ + if r.closed:
│ │ + break
│ │ + assert ret == b'foobarbaz'
│ │ +
│ │ + @onlyBrotlipy()
│ │ + def test_decode_brotli_error(self):
│ │ + fp = BytesIO(b'foo')
│ │ + with pytest.raises(DecodeError):
│ │ + HTTPResponse(fp, headers={'content-encoding': 'br'})
│ │ +
│ │ def test_multi_decoding_deflate_deflate(self):
│ │ data = zlib.compress(zlib.compress(b'foo'))
│ │
│ │ fp = BytesIO(data)
│ │ r = HTTPResponse(fp, headers={'content-encoding': 'deflate, deflate'})
│ │
│ │ assert r.data == b'foo'
│ │ @@ -704,14 +735,49 @@
│ │ status=301, redirect_location='https://example.com/'),
│ │ RequestHistory(method='GET', url='https://example.com/', error=None,
│ │ status=301, redirect_location='https://www.example.com')]
│ │ retry = Retry(history=request_histories)
│ │ resp = HTTPResponse(fp, retries=retry)
│ │ assert resp.geturl() == 'https://www.example.com'
│ │
│ │ + @pytest.mark.parametrize(
│ │ + ["payload", "expected_stream"],
│ │ + [(b"", [b""]),
│ │ + (b"\n", [b"\n"]),
│ │ + (b"abc\ndef", [b"abc\n", b"def"]),
│ │ + (b"Hello\nworld\n\n\n!", [b"Hello\n", b"world\n", b"\n", b"\n", b"!"])]
│ │ + )
│ │ + def test__iter__(self, payload, expected_stream):
│ │ + actual_stream = []
│ │ + for chunk in HTTPResponse(BytesIO(payload), preload_content=False):
│ │ + actual_stream.append(chunk)
│ │ +
│ │ + assert actual_stream == expected_stream
│ │ +
│ │ + def test__iter__decode_content(self):
│ │ + def stream():
│ │ + # Set up a generator to chunk the gzipped body
│ │ + compress = zlib.compressobj(6, zlib.DEFLATED, 16 + zlib.MAX_WBITS)
│ │ + data = compress.compress(b'foo\nbar')
│ │ + data += compress.flush()
│ │ + for i in range(0, len(data), 2):
│ │ + yield data[i:i + 2]
│ │ +
│ │ + fp = MockChunkedEncodingResponse(list(stream()))
│ │ + r = httplib.HTTPResponse(MockSock)
│ │ + r.fp = fp
│ │ + headers = {'transfer-encoding': 'chunked', 'content-encoding': 'gzip'}
│ │ + resp = HTTPResponse(r, preload_content=False, headers=headers)
│ │ +
│ │ + data = b''
│ │ + for c in resp:
│ │ + data += c
│ │ +
│ │ + assert b'foo\nbar' == data
│ │ +
│ │
│ │ class MockChunkedEncodingResponse(object):
│ │
│ │ def __init__(self, content):
│ │ """
│ │ content: collection of str, each str is a chunk in response
│ │ """
│ --- urllib3-1.24.1/docs/conf.py
├── +++ urllib3-1.25.3/docs/conf.py
│┄ Files similar despite different names (difference score: 4)
│ │ @@ -130,15 +130,15 @@
│ │ html_theme = 'alabaster'
│ │
│ │ # Theme options are theme-specific and customize the look and feel of a theme
│ │ # further. For a list of options available for each theme, see the
│ │ # documentation.
│ │ html_theme_options = {
│ │ 'description': 'Sanity-friendly HTTP client.',
│ │ - 'github_user': 'shazow',
│ │ + 'github_user': 'urllib3',
│ │ 'github_repo': 'urllib3',
│ │ 'github_button': False,
│ │ 'github_banner': True,
│ │ 'travis_button': True,
│ │ 'show_powered_by': False,
│ │ 'font_family': "'Roboto', Georgia, sans",
│ │ 'head_font_family': "'Roboto', Georgia, serif",
│ │ @@ -267,8 +267,8 @@
│ │ # (source start file, name, description, authors, manual section).
│ │ man_pages = [
│ │ ('index', 'urllib3', u'urllib3 Documentation',
│ │ [u'Andrey Petrov'], 1)
│ │ ]
│ │
│ │ intersphinx_mapping = {
│ │ - 'python': ('https://docs.python.org/3.5', None),}
│ │ + 'python': ('https://docs.python.org/3.7', None),}
│ --- urllib3-1.24.1/dummyserver/certs/server.key
├── +++ urllib3-1.25.3/dummyserver/certs/server.key
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/connectionpool.py
├── +++ urllib3-1.25.3/src/urllib3/connectionpool.py
│┄ Files similar despite different names (difference score: 11)
│ │ @@ -22,14 +22,15 @@
│ │ TimeoutError,
│ │ InsecureRequestWarning,
│ │ NewConnectionError,
│ │ )
│ │ from .packages.ssl_match_hostname import CertificateError
│ │ from .packages import six
│ │ from .packages.six.moves import queue
│ │ +from .packages.rfc3986.normalizers import normalize_host
│ │ from .connection import (
│ │ port_by_scheme,
│ │ DummyConnection,
│ │ HTTPConnection, HTTPSConnection, VerifiedHTTPSConnection,
│ │ HTTPException, BaseSSLError,
│ │ )
│ │ from .request import RequestMethods
│ │ @@ -61,15 +62,15 @@
│ │ scheme = None
│ │ QueueCls = LifoQueue
│ │
│ │ def __init__(self, host, port=None):
│ │ if not host:
│ │ raise LocationValueError("No host specified.")
│ │
│ │ - self.host = _ipv6_host(host, self.scheme)
│ │ + self.host = _normalize_host(host, scheme=self.scheme)
│ │ self._proxy_host = host.lower()
│ │ self.port = port
│ │
│ │ def __str__(self):
│ │ return '%s(host=%r, port=%r)' % (type(self).__name__,
│ │ self.host, self.port)
│ │
│ │ @@ -369,17 +370,19 @@
│ │ if read_timeout is Timeout.DEFAULT_TIMEOUT:
│ │ conn.sock.settimeout(socket.getdefaulttimeout())
│ │ else: # None or a value
│ │ conn.sock.settimeout(read_timeout)
│ │
│ │ # Receive the response from the server
│ │ try:
│ │ - try: # Python 2.7, use buffering of HTTP responses
│ │ + try:
│ │ + # Python 2.7, use buffering of HTTP responses
│ │ httplib_response = conn.getresponse(buffering=True)
│ │ - except TypeError: # Python 3
│ │ + except TypeError:
│ │ + # Python 3
│ │ try:
│ │ httplib_response = conn.getresponse()
│ │ except Exception as e:
│ │ # Remove the TypeError from the exception chain in Python 3;
│ │ # otherwise it looks like a programming error was the cause.
│ │ six.raise_from(e, None)
│ │ except (SocketTimeout, BaseSSLError, SocketError) as e:
│ │ @@ -428,16 +431,16 @@
│ │ connection pool.
│ │ """
│ │ if url.startswith('/'):
│ │ return True
│ │
│ │ # TODO: Add optional support for socket.gethostbyname checking.
│ │ scheme, host, port = get_host(url)
│ │ -
│ │ - host = _ipv6_host(host, self.scheme)
│ │ + if host is not None:
│ │ + host = _normalize_host(host, scheme=scheme)
│ │
│ │ # Use explicit default port for comparison when none is given
│ │ if self.port and not port:
│ │ port = port_by_scheme.get(scheme)
│ │ elif not self.port and port == port_by_scheme.get(scheme):
│ │ port = None
│ │
│ │ @@ -668,15 +671,15 @@
│ │
│ │ def drain_and_release_conn(response):
│ │ try:
│ │ # discard any remaining response body, the connection will be
│ │ # released back to the pool once the entire response is read
│ │ response.read()
│ │ except (TimeoutError, HTTPException, SocketError, ProtocolError,
│ │ - BaseSSLError, SSLError) as e:
│ │ + BaseSSLError, SSLError):
│ │ pass
│ │
│ │ # Handle redirect?
│ │ redirect_location = redirect and response.get_redirect_location()
│ │ if redirect_location:
│ │ if response.status == 303:
│ │ method = 'GET'
│ │ @@ -742,55 +745,54 @@
│ │ instead of :class:`.HTTPSConnection`.
│ │
│ │ :class:`.VerifiedHTTPSConnection` uses one of ``assert_fingerprint``,
│ │ ``assert_hostname`` and ``host`` in this order to verify connections.
│ │ If ``assert_hostname`` is False, no verification is done.
│ │
│ │ The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs``,
│ │ - ``ca_cert_dir``, and ``ssl_version`` are only used if :mod:`ssl` is
│ │ - available and are fed into :meth:`urllib3.util.ssl_wrap_socket` to upgrade
│ │ + ``ca_cert_dir``, ``ssl_version``, ``key_password`` are only used if :mod:`ssl`
│ │ + is available and are fed into :meth:`urllib3.util.ssl_wrap_socket` to upgrade
│ │ the connection socket into an SSL socket.
│ │ """
│ │
│ │ scheme = 'https'
│ │ ConnectionCls = HTTPSConnection
│ │
│ │ def __init__(self, host, port=None,
│ │ strict=False, timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1,
│ │ block=False, headers=None, retries=None,
│ │ _proxy=None, _proxy_headers=None,
│ │ key_file=None, cert_file=None, cert_reqs=None,
│ │ - ca_certs=None, ssl_version=None,
│ │ + key_password=None, ca_certs=None, ssl_version=None,
│ │ assert_hostname=None, assert_fingerprint=None,
│ │ ca_cert_dir=None, **conn_kw):
│ │
│ │ HTTPConnectionPool.__init__(self, host, port, strict, timeout, maxsize,
│ │ block, headers, retries, _proxy, _proxy_headers,
│ │ **conn_kw)
│ │
│ │ - if ca_certs and cert_reqs is None:
│ │ - cert_reqs = 'CERT_REQUIRED'
│ │ -
│ │ self.key_file = key_file
│ │ self.cert_file = cert_file
│ │ self.cert_reqs = cert_reqs
│ │ + self.key_password = key_password
│ │ self.ca_certs = ca_certs
│ │ self.ca_cert_dir = ca_cert_dir
│ │ self.ssl_version = ssl_version
│ │ self.assert_hostname = assert_hostname
│ │ self.assert_fingerprint = assert_fingerprint
│ │
│ │ def _prepare_conn(self, conn):
│ │ """
│ │ Prepare the ``connection`` for :meth:`urllib3.util.ssl_wrap_socket`
│ │ and establish the tunnel if proxy is used.
│ │ """
│ │
│ │ if isinstance(conn, VerifiedHTTPSConnection):
│ │ conn.set_cert(key_file=self.key_file,
│ │ + key_password=self.key_password,
│ │ cert_file=self.cert_file,
│ │ cert_reqs=self.cert_reqs,
│ │ ca_certs=self.ca_certs,
│ │ ca_cert_dir=self.ca_cert_dir,
│ │ assert_hostname=self.assert_hostname,
│ │ assert_fingerprint=self.assert_fingerprint)
│ │ conn.ssl_version = self.ssl_version
│ │ @@ -820,15 +822,17 @@
│ │ actual_port = self.port
│ │ if self.proxy is not None:
│ │ actual_host = self.proxy.host
│ │ actual_port = self.proxy.port
│ │
│ │ conn = self.ConnectionCls(host=actual_host, port=actual_port,
│ │ timeout=self.timeout.connect_timeout,
│ │ - strict=self.strict, **self.conn_kw)
│ │ + strict=self.strict, cert_file=self.cert_file,
│ │ + key_file=self.key_file, key_password=self.key_password,
│ │ + **self.conn_kw)
│ │
│ │ return self._prepare_conn(conn)
│ │
│ │ def _validate_conn(self, conn):
│ │ """
│ │ Called right before a request is made, after the socket is created.
│ │ """
│ │ @@ -871,26 +875,23 @@
│ │ port = port or port_by_scheme.get(scheme, 80)
│ │ if scheme == 'https':
│ │ return HTTPSConnectionPool(host, port=port, **kw)
│ │ else:
│ │ return HTTPConnectionPool(host, port=port, **kw)
│ │
│ │
│ │ -def _ipv6_host(host, scheme):
│ │ +def _normalize_host(host, scheme):
│ │ """
│ │ - Process IPv6 address literals
│ │ + Normalize hosts for comparisons and use with sockets.
│ │ """
│ │
│ │ # httplib doesn't like it when we include brackets in IPv6 addresses
│ │ # Specifically, if we include brackets but also pass the port then
│ │ # httplib crazily doubles up the square brackets on the Host header.
│ │ # Instead, we need to make sure we never pass ``None`` as the port.
│ │ # However, for backward compatibility reasons we can't actually
│ │ # *assert* that. See http://bugs.python.org/issue28539
│ │ - #
│ │ - # Also if an IPv6 address literal has a zone identifier, the
│ │ - # percent sign might be URIencoded, convert it back into ASCII
│ │ if host.startswith('[') and host.endswith(']'):
│ │ - host = host.replace('%25', '%').strip('[]')
│ │ + host = host.strip('[]')
│ │ if scheme in NORMALIZABLE_SCHEMES:
│ │ - host = host.lower()
│ │ + host = normalize_host(host)
│ │ return host
│ --- urllib3-1.24.1/src/urllib3/contrib/pyopenssl.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/pyopenssl.py
│┄ Files similar despite different names (difference score: 11)
│ │ @@ -66,35 +66,35 @@
│ │ import logging
│ │ import ssl
│ │ from ..packages import six
│ │ import sys
│ │
│ │ from .. import util
│ │
│ │ +
│ │ __all__ = ['inject_into_urllib3', 'extract_from_urllib3']
│ │
│ │ # SNI always works.
│ │ HAS_SNI = True
│ │
│ │ # Map from urllib3 to PyOpenSSL compatible parameter-values.
│ │ _openssl_versions = {
│ │ - ssl.PROTOCOL_SSLv23: OpenSSL.SSL.SSLv23_METHOD,
│ │ + util.PROTOCOL_TLS: OpenSSL.SSL.SSLv23_METHOD,
│ │ ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD,
│ │ }
│ │
│ │ +if hasattr(ssl, 'PROTOCOL_SSLv3') and hasattr(OpenSSL.SSL, 'SSLv3_METHOD'):
│ │ + _openssl_versions[ssl.PROTOCOL_SSLv3] = OpenSSL.SSL.SSLv3_METHOD
│ │ +
│ │ if hasattr(ssl, 'PROTOCOL_TLSv1_1') and hasattr(OpenSSL.SSL, 'TLSv1_1_METHOD'):
│ │ _openssl_versions[ssl.PROTOCOL_TLSv1_1] = OpenSSL.SSL.TLSv1_1_METHOD
│ │
│ │ if hasattr(ssl, 'PROTOCOL_TLSv1_2') and hasattr(OpenSSL.SSL, 'TLSv1_2_METHOD'):
│ │ _openssl_versions[ssl.PROTOCOL_TLSv1_2] = OpenSSL.SSL.TLSv1_2_METHOD
│ │
│ │ -try:
│ │ - _openssl_versions.update({ssl.PROTOCOL_SSLv3: OpenSSL.SSL.SSLv3_METHOD})
│ │ -except AttributeError:
│ │ - pass
│ │
│ │ _stdlib_to_openssl_verify = {
│ │ ssl.CERT_NONE: OpenSSL.SSL.VERIFY_NONE,
│ │ ssl.CERT_OPTIONAL: OpenSSL.SSL.VERIFY_PEER,
│ │ ssl.CERT_REQUIRED:
│ │ OpenSSL.SSL.VERIFY_PEER + OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
│ │ }
│ │ @@ -113,24 +113,26 @@
│ │
│ │
│ │ def inject_into_urllib3():
│ │ 'Monkey-patch urllib3 with PyOpenSSL-backed SSL-support.'
│ │
│ │ _validate_dependencies_met()
│ │
│ │ + util.SSLContext = PyOpenSSLContext
│ │ util.ssl_.SSLContext = PyOpenSSLContext
│ │ util.HAS_SNI = HAS_SNI
│ │ util.ssl_.HAS_SNI = HAS_SNI
│ │ util.IS_PYOPENSSL = True
│ │ util.ssl_.IS_PYOPENSSL = True
│ │
│ │
│ │ def extract_from_urllib3():
│ │ 'Undo monkey-patching by :func:`inject_into_urllib3`.'
│ │
│ │ + util.SSLContext = orig_util_SSLContext
│ │ util.ssl_.SSLContext = orig_util_SSLContext
│ │ util.HAS_SNI = orig_util_HAS_SNI
│ │ util.ssl_.HAS_SNI = orig_util_HAS_SNI
│ │ util.IS_PYOPENSSL = False
│ │ util.ssl_.IS_PYOPENSSL = False
│ │
│ │
│ │ @@ -180,14 +182,18 @@
│ │ if name.startswith(prefix):
│ │ name = name[len(prefix):]
│ │ return prefix.encode('ascii') + idna.encode(name)
│ │ return idna.encode(name)
│ │ except idna.core.IDNAError:
│ │ return None
│ │
│ │ + # Don't send IPv6 addresses through the IDNA encoder.
│ │ + if ':' in name:
│ │ + return name
│ │ +
│ │ name = idna_encode(name)
│ │ if name is None:
│ │ return None
│ │ elif sys.version_info >= (3, 0):
│ │ name = name.decode('utf-8')
│ │ return name
│ │
│ │ @@ -272,46 +278,54 @@
│ │ try:
│ │ data = self.connection.recv(*args, **kwargs)
│ │ except OpenSSL.SSL.SysCallError as e:
│ │ if self.suppress_ragged_eofs and e.args == (-1, 'Unexpected EOF'):
│ │ return b''
│ │ else:
│ │ raise SocketError(str(e))
│ │ - except OpenSSL.SSL.ZeroReturnError as e:
│ │ + except OpenSSL.SSL.ZeroReturnError:
│ │ if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN:
│ │ return b''
│ │ else:
│ │ raise
│ │ except OpenSSL.SSL.WantReadError:
│ │ if not util.wait_for_read(self.socket, self.socket.gettimeout()):
│ │ raise timeout('The read operation timed out')
│ │ else:
│ │ return self.recv(*args, **kwargs)
│ │ +
│ │ + # TLS 1.3 post-handshake authentication
│ │ + except OpenSSL.SSL.Error as e:
│ │ + raise ssl.SSLError("read error: %r" % e)
│ │ else:
│ │ return data
│ │
│ │ def recv_into(self, *args, **kwargs):
│ │ try:
│ │ return self.connection.recv_into(*args, **kwargs)
│ │ except OpenSSL.SSL.SysCallError as e:
│ │ if self.suppress_ragged_eofs and e.args == (-1, 'Unexpected EOF'):
│ │ return 0
│ │ else:
│ │ raise SocketError(str(e))
│ │ - except OpenSSL.SSL.ZeroReturnError as e:
│ │ + except OpenSSL.SSL.ZeroReturnError:
│ │ if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN:
│ │ return 0
│ │ else:
│ │ raise
│ │ except OpenSSL.SSL.WantReadError:
│ │ if not util.wait_for_read(self.socket, self.socket.gettimeout()):
│ │ raise timeout('The read operation timed out')
│ │ else:
│ │ return self.recv_into(*args, **kwargs)
│ │
│ │ + # TLS 1.3 post-handshake authentication
│ │ + except OpenSSL.SSL.Error as e:
│ │ + raise ssl.SSLError("read error: %r" % e)
│ │ +
│ │ def settimeout(self, timeout):
│ │ return self.socket.settimeout(timeout)
│ │
│ │ def _send_until_done(self, data):
│ │ while True:
│ │ try:
│ │ return self.connection.send(data)
│ │ @@ -356,14 +370,17 @@
│ │ return {
│ │ 'subject': (
│ │ (('commonName', x509.get_subject().CN),),
│ │ ),
│ │ 'subjectAltName': get_subj_alt_name(x509)
│ │ }
│ │
│ │ + def version(self):
│ │ + return self.connection.get_protocol_version_name()
│ │ +
│ │ def _reuse(self):
│ │ self._makefile_refs += 1
│ │
│ │ def _drop(self):
│ │ if self._makefile_refs < 1:
│ │ self.close()
│ │ else:
│ │ @@ -428,15 +445,17 @@
│ │ self._ctx.load_verify_locations(cafile, capath)
│ │ if cadata is not None:
│ │ self._ctx.load_verify_locations(BytesIO(cadata))
│ │
│ │ def load_cert_chain(self, certfile, keyfile=None, password=None):
│ │ self._ctx.use_certificate_chain_file(certfile)
│ │ if password is not None:
│ │ - self._ctx.set_passwd_cb(lambda max_length, prompt_twice, userdata: password)
│ │ + if not isinstance(password, six.binary_type):
│ │ + password = password.encode('utf-8')
│ │ + self._ctx.set_passwd_cb(lambda *_: password)
│ │ self._ctx.use_privatekey_file(keyfile or certfile)
│ │
│ │ def wrap_socket(self, sock, server_side=False,
│ │ do_handshake_on_connect=True, suppress_ragged_eofs=True,
│ │ server_hostname=None):
│ │ cnx = OpenSSL.SSL.Connection(self._ctx, sock)
│ --- urllib3-1.24.1/test/test_exceptions.py
├── +++ urllib3-1.25.3/test/test_exceptions.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3.egg-info/SOURCES.txt
├── +++ urllib3-1.25.3/src/urllib3.egg-info/SOURCES.txt
│┄ Files similar despite different names (difference score: 49)
│ │ @@ -31,26 +31,29 @@
│ │ dummyserver/certs/client.csr
│ │ dummyserver/certs/client.key
│ │ dummyserver/certs/client.pem
│ │ dummyserver/certs/client_bad.pem
│ │ dummyserver/certs/client_intermediate.key
│ │ dummyserver/certs/client_intermediate.pem
│ │ dummyserver/certs/client_no_intermediate.pem
│ │ +dummyserver/certs/client_password.key
│ │ dummyserver/certs/intermediate.key
│ │ dummyserver/certs/intermediate.pem
│ │ dummyserver/certs/server.combined.pem
│ │ dummyserver/certs/server.crt
│ │ dummyserver/certs/server.csr
│ │ dummyserver/certs/server.ip_san.crt
│ │ +dummyserver/certs/server.ipv6_san.crt
│ │ dummyserver/certs/server.ipv6addr.crt
│ │ dummyserver/certs/server.ipv6addr.key
│ │ dummyserver/certs/server.key
│ │ dummyserver/certs/server.key.org
│ │ dummyserver/certs/server.no_san.crt
│ │ dummyserver/certs/server.no_san.csr
│ │ +dummyserver/certs/server_password.key
│ │ dummyserver/certs/ca_path_test/98a2772e.0
│ │ dummyserver/certs/ca_path_test/b6b9ccf9.0
│ │ dummyserver/certs/ca_path_test/cacert.pem
│ │ src/urllib3/__init__.py
│ │ src/urllib3/_collections.py
│ │ src/urllib3/connection.py
│ │ src/urllib3/connectionpool.py
│ │ @@ -75,14 +78,27 @@
│ │ src/urllib3/contrib/_securetransport/__init__.py
│ │ src/urllib3/contrib/_securetransport/bindings.py
│ │ src/urllib3/contrib/_securetransport/low_level.py
│ │ src/urllib3/packages/__init__.py
│ │ src/urllib3/packages/six.py
│ │ src/urllib3/packages/backports/__init__.py
│ │ src/urllib3/packages/backports/makefile.py
│ │ +src/urllib3/packages/rfc3986/__init__.py
│ │ +src/urllib3/packages/rfc3986/_mixin.py
│ │ +src/urllib3/packages/rfc3986/abnf_regexp.py
│ │ +src/urllib3/packages/rfc3986/api.py
│ │ +src/urllib3/packages/rfc3986/builder.py
│ │ +src/urllib3/packages/rfc3986/compat.py
│ │ +src/urllib3/packages/rfc3986/exceptions.py
│ │ +src/urllib3/packages/rfc3986/iri.py
│ │ +src/urllib3/packages/rfc3986/misc.py
│ │ +src/urllib3/packages/rfc3986/normalizers.py
│ │ +src/urllib3/packages/rfc3986/parseresult.py
│ │ +src/urllib3/packages/rfc3986/uri.py
│ │ +src/urllib3/packages/rfc3986/validators.py
│ │ src/urllib3/packages/ssl_match_hostname/__init__.py
│ │ src/urllib3/packages/ssl_match_hostname/_implementation.py
│ │ src/urllib3/util/__init__.py
│ │ src/urllib3/util/connection.py
│ │ src/urllib3/util/queue.py
│ │ src/urllib3/util/request.py
│ │ src/urllib3/util/response.py
│ --- urllib3-1.24.1/test/test_compatibility.py
├── +++ urllib3-1.25.3/test/test_compatibility.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/README.rst
├── +++ urllib3-1.25.3/dummyserver/certs/README.rst
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/client.key
├── +++ urllib3-1.25.3/dummyserver/certs/client.key
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/packages/ssl_match_hostname/__init__.py
├── +++ urllib3-1.25.3/src/urllib3/packages/ssl_match_hostname/__init__.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/server.ipv6addr.crt
├── +++ urllib3-1.25.3/dummyserver/certs/server.ipv6addr.crt
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/server.crt
├── +++ urllib3-1.25.3/dummyserver/certs/server.crt
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/benchmark.py
├── +++ urllib3-1.25.3/test/benchmark.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/client_intermediate.key
├── +++ urllib3-1.25.3/dummyserver/certs/client_intermediate.key
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/server.combined.pem
├── +++ urllib3-1.25.3/dummyserver/certs/server.combined.pem
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/appengine/test_gae_manager.py
├── +++ urllib3-1.25.3/test/appengine/test_gae_manager.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/CHANGES.rst
├── +++ urllib3-1.25.3/CHANGES.rst
│┄ Files similar despite different names (difference score: 17)
│ │ @@ -1,16 +1,86 @@
│ │ Changes
│ │ =======
│ │
│ │ +1.25.3 (2019-05-23)
│ │ +-------------------
│ │ +
│ │ +* Change ``HTTPSConnection`` to load system CA certificates
│ │ + when ``ca_certs``, ``ca_cert_dir``, and ``ssl_context`` are
│ │ + unspecified. (Pull #1608, Issue #1603)
│ │ +
│ │ +* Upgrade bundled rfc3986 to v1.3.2. (Pull #1609, Issue #1605)
│ │ +
│ │ +
│ │ +1.25.2 (2019-04-28)
│ │ +-------------------
│ │ +
│ │ +* Change ``is_ipaddress`` to not detect IPvFuture addresses. (Pull #1583)
│ │ +
│ │ +* Change ``parse_url`` to percent-encode invalid characters within the
│ │ + path, query, and target components. (Pull #1586)
│ │ +
│ │ +
│ │ +1.25.1 (2019-04-24)
│ │ +-------------------
│ │ +
│ │ +* Add support for Google's ``Brotli`` package. (Pull #1572, Pull #1579)
│ │ +
│ │ +* Upgrade bundled rfc3986 to v1.3.1 (Pull #1578)
│ │ +
│ │ +
│ │ +1.25 (2019-04-22)
│ │ +-----------------
│ │ +
│ │ +* Require and validate certificates by default when using HTTPS (Pull #1507)
│ │ +
│ │ +* Upgraded ``urllib3.utils.parse_url()`` to be RFC 3986 compliant. (Pull #1487)
│ │ +
│ │ +* Added support for ``key_password`` for ``HTTPSConnectionPool`` to use
│ │ + encrypted ``key_file`` without creating your own ``SSLContext`` object. (Pull #1489)
│ │ +
│ │ +* Add TLSv1.3 support to CPython, pyOpenSSL, and SecureTransport ``SSLContext``
│ │ + implementations. (Pull #1496)
│ │ +
│ │ +* Switched the default multipart header encoder from RFC 2231 to HTML 5 working draft. (Issue #303, PR #1492)
│ │ +
│ │ +* Fixed issue where OpenSSL would block if an encrypted client private key was
│ │ + given and no password was given. Instead an ``SSLError`` is raised. (Pull #1489)
│ │ +
│ │ +* Added support for Brotli content encoding. It is enabled automatically if
│ │ + ``brotlipy`` package is installed which can be requested with
│ │ + ``urllib3[brotli]`` extra. (Pull #1532)
│ │ +
│ │ +* Drop ciphers using DSS key exchange from default TLS cipher suites.
│ │ + Improve default ciphers when using SecureTransport. (Pull #1496)
│ │ +
│ │ +* Implemented a more efficient ``HTTPResponse.__iter__()`` method. (Issue #1483)
│ │ +
│ │ +1.24.3 (2019-05-01)
│ │ +-------------------
│ │ +
│ │ +* Apply fix for CVE-2019-9740. (Pull #1591)
│ │ +
│ │ +1.24.2 (2019-04-17)
│ │ +-------------------
│ │ +
│ │ +* Don't load system certificates by default when any other ``ca_certs``, ``ca_certs_dir`` or
│ │ + ``ssl_context`` parameters are specified.
│ │ +
│ │ +* Remove Authorization header regardless of case when redirecting to cross-site. (Issue #1510)
│ │ +
│ │ +* Add support for IPv6 addresses in subjectAltName section of certificates. (Issue #1269)
│ │ +
│ │ +
│ │ 1.24.1 (2018-11-02)
│ │ -------------------
│ │
│ │ * Remove quadratic behavior within ``GzipDecoder.decompress()`` (Issue #1467)
│ │
│ │ -* Restored functionality of `ciphers` parameter for `create_urllib3_context()`. (Issue #1462)
│ │ +* Restored functionality of ``ciphers`` parameter for ``create_urllib3_context()``. (Issue #1462)
│ │
│ │
│ │ 1.24 (2018-10-16)
│ │ -----------------
│ │
│ │ * Allow key_server_hostname to be specified when initializing a PoolManager to allow custom SNI to be overridden. (Pull #1449)
│ --- urllib3-1.24.1/dummyserver/certs/ca_path_test/98a2772e.0
├── +++ urllib3-1.25.3/dummyserver/certs/ca_path_test/98a2772e.0
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/docs/reference/urllib3.contrib.rst
├── +++ urllib3-1.25.3/docs/reference/urllib3.contrib.rst
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/server.ipv6addr.key
├── +++ urllib3-1.25.3/dummyserver/certs/server.ipv6addr.key
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/contrib/_appengine_environ.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/_appengine_environ.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/__init__.py
├── +++ urllib3-1.25.3/src/urllib3/__init__.py
│┄ Files similar despite different names (difference score: 6)
│ │ @@ -1,11 +1,10 @@
│ │ """
│ │ urllib3 - Thread-safe connection pooling and re-using.
│ │ """
│ │ -
│ │ from __future__ import absolute_import
│ │ import warnings
│ │
│ │ from .connectionpool import (
│ │ HTTPConnectionPool,
│ │ HTTPSConnectionPool,
│ │ connection_from_url
│ │ @@ -23,15 +22,15 @@
│ │
│ │ # Set default logging handler to avoid "No handler found" warnings.
│ │ import logging
│ │ from logging import NullHandler
│ │
│ │ __author__ = 'Andrey Petrov ([email protected])'
│ │ __license__ = 'MIT'
│ │ -__version__ = '1.24.1'
│ │ +__version__ = '1.25.3'
│ │
│ │ __all__ = (
│ │ 'HTTPConnectionPool',
│ │ 'HTTPSConnectionPool',
│ │ 'PoolManager',
│ │ 'ProxyManager',
│ │ 'HTTPResponse',
│ --- urllib3-1.24.1/dummyserver/certs/cacert.key
├── +++ urllib3-1.25.3/dummyserver/certs/cacert.key
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/contrib/appengine.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/appengine.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/packages/backports/makefile.py
├── +++ urllib3-1.25.3/src/urllib3/packages/backports/makefile.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/packages/ssl_match_hostname/_implementation.py
├── +++ urllib3-1.25.3/src/urllib3/packages/ssl_match_hostname/_implementation.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/proxy.py
├── +++ urllib3-1.25.3/dummyserver/proxy.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/poolmanager.py
├── +++ urllib3-1.25.3/src/urllib3/poolmanager.py
│┄ Files similar despite different names (difference score: 6)
│ │ @@ -3,55 +3,58 @@
│ │ import functools
│ │ import logging
│ │
│ │ from ._collections import RecentlyUsedContainer
│ │ from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool
│ │ from .connectionpool import port_by_scheme
│ │ from .exceptions import LocationValueError, MaxRetryError, ProxySchemeUnknown
│ │ +from .packages import six
│ │ from .packages.six.moves.urllib.parse import urljoin
│ │ from .request import RequestMethods
│ │ from .util.url import parse_url
│ │ from .util.retry import Retry
│ │
│ │
│ │ __all__ = ['PoolManager', 'ProxyManager', 'proxy_from_url']
│ │
│ │
│ │ log = logging.getLogger(__name__)
│ │
│ │ SSL_KEYWORDS = ('key_file', 'cert_file', 'cert_reqs', 'ca_certs',
│ │ - 'ssl_version', 'ca_cert_dir', 'ssl_context')
│ │ + 'ssl_version', 'ca_cert_dir', 'ssl_context',
│ │ + 'key_password')
│ │
│ │ # All known keyword arguments that could be provided to the pool manager, its
│ │ # pools, or the underlying connections. This is used to construct a pool key.
│ │ _key_fields = (
│ │ 'key_scheme', # str
│ │ 'key_host', # str
│ │ 'key_port', # int
│ │ 'key_timeout', # int or float or Timeout
│ │ 'key_retries', # int or Retry
│ │ 'key_strict', # bool
│ │ 'key_block', # bool
│ │ 'key_source_address', # str
│ │ 'key_key_file', # str
│ │ + 'key_key_password', # str
│ │ 'key_cert_file', # str
│ │ 'key_cert_reqs', # str
│ │ 'key_ca_certs', # str
│ │ 'key_ssl_version', # str
│ │ 'key_ca_cert_dir', # str
│ │ 'key_ssl_context', # instance of ssl.SSLContext or urllib3.util.ssl_.SSLContext
│ │ 'key_maxsize', # int
│ │ 'key_headers', # dict
│ │ 'key__proxy', # parsed proxy url
│ │ 'key__proxy_headers', # dict
│ │ 'key_socket_options', # list of (level (int), optname (int), value (int or str)) tuples
│ │ 'key__socks_options', # dict
│ │ 'key_assert_hostname', # bool or string
│ │ 'key_assert_fingerprint', # str
│ │ - 'key_server_hostname', #str
│ │ + 'key_server_hostname', # str
│ │ )
│ │
│ │ #: The namedtuple class used to construct keys for the connection pool.
│ │ #: All custom key schemes should include the fields in this key at a minimum.
│ │ PoolKey = collections.namedtuple('PoolKey', _key_fields)
│ │
│ │
│ │ @@ -338,16 +341,18 @@
│ │ retries = Retry.from_int(retries, redirect=redirect)
│ │
│ │ # Strip headers marked as unsafe to forward to the redirected location.
│ │ # Check remove_headers_on_redirect to avoid a potential network call within
│ │ # conn.is_same_host() which may use socket.gethostbyname() in the future.
│ │ if (retries.remove_headers_on_redirect
│ │ and not conn.is_same_host(redirect_location)):
│ │ - for header in retries.remove_headers_on_redirect:
│ │ - kw['headers'].pop(header, None)
│ │ + headers = list(six.iterkeys(kw['headers']))
│ │ + for header in headers:
│ │ + if header.lower() in retries.remove_headers_on_redirect:
│ │ + kw['headers'].pop(header, None)
│ │
│ │ try:
│ │ retries = retries.increment(method, url, response=response, _pool=conn)
│ │ except MaxRetryError:
│ │ if retries.raise_on_redirect:
│ │ raise
│ │ return response
│ --- urllib3-1.24.1/src/urllib3/util/connection.py
├── +++ urllib3-1.25.3/src/urllib3/util/connection.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/client_no_intermediate.pem
├── +++ urllib3-1.25.3/dummyserver/certs/client_no_intermediate.pem
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/testcase.py
├── +++ urllib3-1.25.3/dummyserver/testcase.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/contrib/test_pyopenssl.py
├── +++ urllib3-1.25.3/test/contrib/test_pyopenssl.py
│┄ Files similar despite different names (difference score: 58)
│ │ @@ -21,21 +21,25 @@
│ │ inject_into_urllib3()
│ │ except ImportError as e:
│ │ pytest.skip('Could not import PyOpenSSL: %r' % e)
│ │
│ │
│ │ def teardown_module():
│ │ try:
│ │ - from urllib3.contrib.securetransport import extract_from_urllib3
│ │ + from urllib3.contrib.pyopenssl import extract_from_urllib3
│ │ extract_from_urllib3()
│ │ except ImportError:
│ │ pass
│ │
│ │
│ │ -from ..with_dummyserver.test_https import TestHTTPS, TestHTTPS_TLSv1 # noqa: F401
│ │ +from ..with_dummyserver.test_https import ( # noqa: F401
│ │ + TestHTTPS, TestHTTPS_TLSv1, TestHTTPS_TLSv1_1,
│ │ + TestHTTPS_TLSv1_2, TestHTTPS_TLSv1_3, TestHTTPS_IPSAN,
│ │ + TestHTTPS_IPv6Addr, TestHTTPS_NoSAN, TestHTTPS_IPV6SAN
│ │ +)
│ │ from ..with_dummyserver.test_socketlevel import ( # noqa: F401
│ │ TestSNI, TestSocketClosing, TestClientCerts
│ │ )
│ │
│ │
│ │ class TestPyOpenSSLHelpers(unittest.TestCase):
│ │ """
│ --- urllib3-1.24.1/test/with_dummyserver/test_connectionpool.py
├── +++ urllib3-1.25.3/test/with_dummyserver/test_connectionpool.py
│┄ Files similar despite different names (difference score: 3)
│ │ @@ -210,14 +210,16 @@
│ │ # The connect should succeed and this should hit the read timeout
│ │ timeout = Timeout(connect=3, read=5, total=SHORT_TIMEOUT)
│ │ pool = HTTPConnectionPool(self.host, self.port, timeout=timeout, retries=False)
│ │ self.addCleanup(pool.close)
│ │ self.assertRaises(ReadTimeoutError, pool.request, 'GET', '/')
│ │
│ │ def test_create_connection_timeout(self):
│ │ + self.start_basic_handler(block_send=Event(), num=0) # needed for self.port
│ │ +
│ │ timeout = Timeout(connect=SHORT_TIMEOUT, total=LONG_TIMEOUT)
│ │ pool = HTTPConnectionPool(TARPIT_HOST, self.port, timeout=timeout, retries=False)
│ │ self.addCleanup(pool.close)
│ │ conn = pool._new_conn()
│ │ self.assertRaises(ConnectTimeoutError, conn.connect)
│ │
│ │
│ │ @@ -508,14 +510,31 @@
│ │ """
│ │ for i, line in enumerate(body):
│ │ if line.startswith(b'--'):
│ │ continue
│ │
│ │ self.assertEqual(body[i], expected_body[i])
│ │
│ │ + def test_post_with_multipart__iter__(self):
│ │ + data = {'hello': 'world'}
│ │ + r = self.pool.request('POST', '/echo',
│ │ + fields=data,
│ │ + preload_content=False,
│ │ + multipart_boundary="boundary",
│ │ + encode_multipart=True)
│ │ +
│ │ + chunks = [chunk for chunk in r]
│ │ + assert chunks == [
│ │ + b"--boundary\r\n",
│ │ + b'Content-Disposition: form-data; name="hello"\r\n',
│ │ + b'\r\n',
│ │ + b'world\r\n',
│ │ + b"--boundary--\r\n"
│ │ + ]
│ │ +
│ │ def test_check_gzip(self):
│ │ r = self.pool.request('GET', '/encodingrequest',
│ │ headers={'accept-encoding': 'gzip'})
│ │ self.assertEqual(r.headers.get('content-encoding'), 'gzip')
│ │ self.assertEqual(r.data, b'hello, world!')
│ │
│ │ def test_check_deflate(self):
│ --- urllib3-1.24.1/PKG-INFO
├── +++ urllib3-1.25.3/PKG-INFO
│┄ Files similar despite different names (difference score: 7)
│ │ @@ -1,10 +1,10 @@
│ │ Metadata-Version: 2.1
│ │ Name: urllib3
│ │ -Version: 1.24.1
│ │ +Version: 1.25.3
│ │ Summary: HTTP library with thread-safe connection pooling, file post, and more.
│ │ Home-page: https://urllib3.readthedocs.io/
│ │ Author: Andrey Petrov
│ │ Author-email: [email protected]
│ │ License: MIT
│ │ Description: urllib3
│ │ =======
│ │ @@ -25,33 +25,33 @@
│ │ :alt: Coverage Status
│ │ :target: https://codecov.io/gh/urllib3/urllib3
│ │
│ │ .. image:: https://img.shields.io/pypi/v/urllib3.svg?maxAge=86400
│ │ :alt: PyPI version
│ │ :target: https://pypi.org/project/urllib3/
│ │
│ │ - .. image:: https://www.bountysource.com/badge/tracker?tracker_id=192525
│ │ - :alt: Bountysource
│ │ - :target: https://www.bountysource.com/trackers/192525-urllib3?utm_source=192525&utm_medium=shield&utm_campaign=TRACKER_BADGE
│ │ -
│ │ .. image:: https://badges.gitter.im/python-urllib3/Lobby.svg
│ │ :alt: Gitter
│ │ :target: https://gitter.im/python-urllib3/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
│ │
│ │ + .. image:: https://tidelift.com/badges/github/urllib3/urllib3
│ │ + :alt: Tidelift Dependencies
│ │ + :target: https://tidelift.com/subscription/pkg/pypi-urllib3?utm_source=pypi-urllib3&utm_medium=referral&utm_campaign=docs
│ │ +
│ │ urllib3 is a powerful, *sanity-friendly* HTTP client for Python. Much of the
│ │ Python ecosystem already uses urllib3 and you should too.
│ │ urllib3 brings many critical features that are missing from the Python
│ │ standard libraries:
│ │
│ │ - Thread safety.
│ │ - Connection pooling.
│ │ - Client-side SSL/TLS verification.
│ │ - File uploads with multipart encoding.
│ │ - Helpers for retrying requests and dealing with HTTP redirects.
│ │ - - Support for gzip and deflate encoding.
│ │ + - Support for gzip, deflate, and brotli encoding.
│ │ - Proxy support for HTTP and SOCKS.
│ │ - 100% test coverage.
│ │
│ │ urllib3 is powerful and easy to use::
│ │
│ │ >>> import urllib3
│ │ >>> http = urllib3.PoolManager()
│ │ @@ -85,50 +85,143 @@
│ │ ------------
│ │
│ │ urllib3 happily accepts contributions. Please see our
│ │ `contributing documentation <https://urllib3.readthedocs.io/en/latest/contributing.html>`_
│ │ for some tips on getting started.
│ │
│ │
│ │ + Security Disclosures
│ │ + --------------------
│ │ +
│ │ + To report a security vulnerability, please use the
│ │ + `Tidelift security contact <https://tidelift.com/security>`_.
│ │ + Tidelift will coordinate the fix and disclosure with maintainers.
│ │ +
│ │ Maintainers
│ │ -----------
│ │
│ │ - `@theacodes <https://github.com/theacodes>`_ (Thea Flowers)
│ │ - - `@SethMichaelLarson <https://github.com/SethMichaelLarson>`_ (Seth M. Larson)
│ │ - - `@haikuginger <https://github.com/haikuginger>`_ (Jesse Shapiro)
│ │ + - `@sethmlarson <https://github.com/sethmlarson>`_ (Seth M. Larson)
│ │ + - `@haikuginger <https://github.com/haikuginger>`_ (Jess Shapiro)
│ │ - `@lukasa <https://github.com/lukasa>`_ (Cory Benfield)
│ │ - `@sigmavirus24 <https://github.com/sigmavirus24>`_ (Ian Cordasco)
│ │ - `@shazow <https://github.com/shazow>`_ (Andrey Petrov)
│ │
│ │ 👋
│ │
│ │
│ │ Sponsorship
│ │ -----------
│ │
│ │ + .. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White_small.png
│ │ + :width: 75
│ │ + :alt: Tidelift
│ │ +
│ │ + .. list-table::
│ │ + :widths: 10 100
│ │ +
│ │ + * - |tideliftlogo|
│ │ + - Professional support for urllib3 is available as part of the `Tidelift
│ │ + Subscription`_. Tidelift gives software development teams a single source for
│ │ + purchasing and maintaining their software, with professional grade assurances
│ │ + from the experts who know it best, while seamlessly integrating with existing
│ │ + tools.
│ │ +
│ │ + .. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-urllib3?utm_source=pypi-urllib3&utm_medium=referral&utm_campaign=readme
│ │ +
│ │ If your company benefits from this library, please consider `sponsoring its
│ │ - development <https://urllib3.readthedocs.io/en/latest/contributing.html#sponsorship>`_.
│ │ + development <https://urllib3.readthedocs.io/en/latest/contributing.html#sponsorship-project-grants>`_.
│ │
│ │ Sponsors include:
│ │
│ │ - Google Cloud Platform (2018-present), sponsors `@theacodes <https://github.com/theacodes>`_'s work on an ongoing basis
│ │ - - Abbott (2018-present), sponsors `@SethMichaelLarson <https://github.com/SethMichaelLarson>`_'s work on an ongoing basis
│ │ - - Akamai (2017-present), sponsors `@haikuginger <https://github.com/haikuginger>`_'s work on an ongoing basis
│ │ + - Abbott (2018-present), sponsors `@sethmlarson <https://github.com/sethmlarson>`_'s work on an ongoing basis
│ │ + - Akamai (2017-2018), sponsored `@haikuginger <https://github.com/haikuginger>`_'s work on urllib3
│ │ - Hewlett Packard Enterprise (2016-2017), sponsored `@Lukasa’s <https://github.com/Lukasa>`_ work on urllib3
│ │
│ │
│ │ Changes
│ │ =======
│ │
│ │ + 1.25.3 (2019-05-23)
│ │ + -------------------
│ │ +
│ │ + * Change ``HTTPSConnection`` to load system CA certificates
│ │ + when ``ca_certs``, ``ca_cert_dir``, and ``ssl_context`` are
│ │ + unspecified. (Pull #1608, Issue #1603)
│ │ +
│ │ + * Upgrade bundled rfc3986 to v1.3.2. (Pull #1609, Issue #1605)
│ │ +
│ │ +
│ │ + 1.25.2 (2019-04-28)
│ │ + -------------------
│ │ +
│ │ + * Change ``is_ipaddress`` to not detect IPvFuture addresses. (Pull #1583)
│ │ +
│ │ + * Change ``parse_url`` to percent-encode invalid characters within the
│ │ + path, query, and target components. (Pull #1586)
│ │ +
│ │ +
│ │ + 1.25.1 (2019-04-24)
│ │ + -------------------
│ │ +
│ │ + * Add support for Google's ``Brotli`` package. (Pull #1572, Pull #1579)
│ │ +
│ │ + * Upgrade bundled rfc3986 to v1.3.1 (Pull #1578)
│ │ +
│ │ +
│ │ + 1.25 (2019-04-22)
│ │ + -----------------
│ │ +
│ │ + * Require and validate certificates by default when using HTTPS (Pull #1507)
│ │ +
│ │ + * Upgraded ``urllib3.utils.parse_url()`` to be RFC 3986 compliant. (Pull #1487)
│ │ +
│ │ + * Added support for ``key_password`` for ``HTTPSConnectionPool`` to use
│ │ + encrypted ``key_file`` without creating your own ``SSLContext`` object. (Pull #1489)
│ │ +
│ │ + * Add TLSv1.3 support to CPython, pyOpenSSL, and SecureTransport ``SSLContext``
│ │ + implementations. (Pull #1496)
│ │ +
│ │ + * Switched the default multipart header encoder from RFC 2231 to HTML 5 working draft. (Issue #303, PR #1492)
│ │ +
│ │ + * Fixed issue where OpenSSL would block if an encrypted client private key was
│ │ + given and no password was given. Instead an ``SSLError`` is raised. (Pull #1489)
│ │ +
│ │ + * Added support for Brotli content encoding. It is enabled automatically if
│ │ + ``brotlipy`` package is installed which can be requested with
│ │ + ``urllib3[brotli]`` extra. (Pull #1532)
│ │ +
│ │ + * Drop ciphers using DSS key exchange from default TLS cipher suites.
│ │ + Improve default ciphers when using SecureTransport. (Pull #1496)
│ │ +
│ │ + * Implemented a more efficient ``HTTPResponse.__iter__()`` method. (Issue #1483)
│ │ +
│ │ + 1.24.3 (2019-05-01)
│ │ + -------------------
│ │ +
│ │ + * Apply fix for CVE-2019-9740. (Pull #1591)
│ │ +
│ │ + 1.24.2 (2019-04-17)
│ │ + -------------------
│ │ +
│ │ + * Don't load system certificates by default when any other ``ca_certs``, ``ca_certs_dir`` or
│ │ + ``ssl_context`` parameters are specified.
│ │ +
│ │ + * Remove Authorization header regardless of case when redirecting to cross-site. (Issue #1510)
│ │ +
│ │ + * Add support for IPv6 addresses in subjectAltName section of certificates. (Issue #1269)
│ │ +
│ │ +
│ │ 1.24.1 (2018-11-02)
│ │ -------------------
│ │
│ │ * Remove quadratic behavior within ``GzipDecoder.decompress()`` (Issue #1467)
│ │
│ │ - * Restored functionality of `ciphers` parameter for `create_urllib3_context()`. (Issue #1462)
│ │ + * Restored functionality of ``ciphers`` parameter for ``create_urllib3_context()``. (Issue #1462)
│ │
│ │
│ │ 1.24 (2018-10-16)
│ │ -----------------
│ │
│ │ * Allow key_server_hostname to be specified when initializing a PoolManager to allow custom SNI to be overridden. (Pull #1449)
│ │
│ │ @@ -1088,14 +1181,17 @@
│ │ Classifier: Programming Language :: Python
│ │ Classifier: Programming Language :: Python :: 2
│ │ Classifier: Programming Language :: Python :: 2.7
│ │ Classifier: Programming Language :: Python :: 3
│ │ Classifier: Programming Language :: Python :: 3.4
│ │ Classifier: Programming Language :: Python :: 3.5
│ │ Classifier: Programming Language :: Python :: 3.6
│ │ +Classifier: Programming Language :: Python :: 3.7
│ │ +Classifier: Programming Language :: Python :: 3.8
│ │ Classifier: Programming Language :: Python :: Implementation :: CPython
│ │ Classifier: Programming Language :: Python :: Implementation :: PyPy
│ │ Classifier: Topic :: Internet :: WWW/HTTP
│ │ Classifier: Topic :: Software Development :: Libraries
│ │ Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4
│ │ Provides-Extra: socks
│ │ Provides-Extra: secure
│ │ +Provides-Extra: brotli
│ --- urllib3-1.24.1/dummyserver/certs/server.no_san.crt
├── +++ urllib3-1.25.3/dummyserver/certs/server.no_san.crt
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/docs/reference/urllib3.util.rst
├── +++ urllib3-1.25.3/docs/reference/urllib3.util.rst
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/server.key.org
├── +++ urllib3-1.25.3/dummyserver/certs/server.key.org
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/intermediate.pem
├── +++ urllib3-1.25.3/dummyserver/certs/intermediate.pem
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/docs/Makefile
├── +++ urllib3-1.25.3/docs/Makefile
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/test_collections.py
├── +++ urllib3-1.25.3/test/test_collections.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/util/wait.py
├── +++ urllib3-1.25.3/src/urllib3/util/wait.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/test_wait.py
├── +++ urllib3-1.25.3/test/test_wait.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/test_queue_monkeypatch.py
├── +++ urllib3-1.25.3/test/test_queue_monkeypatch.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/ca_path_test/cacert.pem
├── +++ urllib3-1.25.3/dummyserver/certs/ca_path_test/b6b9ccf9.0
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/client_bad.pem
├── +++ urllib3-1.25.3/dummyserver/certs/client_bad.pem
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/docs/reference/index.rst
├── +++ urllib3-1.25.3/docs/reference/index.rst
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/with_dummyserver/test_poolmanager.py
├── +++ urllib3-1.25.3/test/with_dummyserver/test_poolmanager.py
│┄ Files similar despite different names (difference score: 23)
│ │ @@ -119,14 +119,25 @@
│ │
│ │ self.assertEqual(r.status, 200)
│ │
│ │ data = json.loads(r.data.decode('utf-8'))
│ │
│ │ self.assertNotIn('Authorization', data)
│ │
│ │ + r = http.request('GET', '%s/redirect' % self.base_url,
│ │ + fields={'target': '%s/headers' % self.base_url_alt},
│ │ + headers={'authorization': 'foo'})
│ │ +
│ │ + self.assertEqual(r.status, 200)
│ │ +
│ │ + data = json.loads(r.data.decode('utf-8'))
│ │ +
│ │ + self.assertNotIn('authorization', data)
│ │ + self.assertNotIn('Authorization', data)
│ │ +
│ │ def test_redirect_cross_host_no_remove_headers(self):
│ │ http = PoolManager()
│ │ self.addCleanup(http.clear)
│ │
│ │ r = http.request('GET', '%s/redirect' % self.base_url,
│ │ fields={'target': '%s/headers' % self.base_url_alt},
│ │ headers={'Authorization': 'foo'},
│ │ @@ -151,14 +162,28 @@
│ │ self.assertEqual(r.status, 200)
│ │
│ │ data = json.loads(r.data.decode('utf-8'))
│ │
│ │ self.assertNotIn('X-API-Secret', data)
│ │ self.assertEqual(data['Authorization'], 'bar')
│ │
│ │ + r = http.request('GET', '%s/redirect' % self.base_url,
│ │ + fields={'target': '%s/headers' % self.base_url_alt},
│ │ + headers={'x-api-secret': 'foo',
│ │ + 'authorization': 'bar'},
│ │ + retries=Retry(remove_headers_on_redirect=['X-API-Secret']))
│ │ +
│ │ + self.assertEqual(r.status, 200)
│ │ +
│ │ + data = json.loads(r.data.decode('utf-8'))
│ │ +
│ │ + self.assertNotIn('x-api-secret', data)
│ │ + self.assertNotIn('X-API-Secret', data)
│ │ + self.assertEqual(data['Authorization'], 'bar')
│ │ +
│ │ def test_raise_on_redirect(self):
│ │ http = PoolManager()
│ │ self.addCleanup(http.clear)
│ │
│ │ r = http.request('GET', '%s/redirect' % self.base_url,
│ │ fields={'target': '%s/redirect?target=%s/' % (self.base_url,
│ │ self.base_url)},
│ --- urllib3-1.24.1/test/contrib/test_securetransport.py
├── +++ urllib3-1.25.3/test/contrib/test_securetransport.py
│┄ Files similar despite different names (difference score: 51)
│ │ @@ -23,15 +23,18 @@
│ │ try:
│ │ from urllib3.contrib.securetransport import extract_from_urllib3
│ │ extract_from_urllib3()
│ │ except ImportError:
│ │ pass
│ │
│ │
│ │ -from ..with_dummyserver.test_https import TestHTTPS, TestHTTPS_TLSv1 # noqa: F401
│ │ +from ..with_dummyserver.test_https import ( # noqa: F401
│ │ + TestHTTPS, TestHTTPS_TLSv1, TestHTTPS_TLSv1_1,
│ │ + TestHTTPS_TLSv1_2, TestHTTPS_TLSv1_3
│ │ +)
│ │ from ..with_dummyserver.test_socketlevel import ( # noqa: F401
│ │ TestSNI, TestSocketClosing, TestClientCerts
│ │ )
│ │
│ │
│ │ def test_no_crash_with_empty_trust_bundle():
│ │ with contextlib.closing(socket.socket()) as s:
│ --- urllib3-1.24.1/dummyserver/certs/intermediate.key
├── +++ urllib3-1.25.3/dummyserver/certs/intermediate.key
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/response.py
├── +++ urllib3-1.25.3/src/urllib3/response.py
│┄ Files similar despite different names (difference score: 11)
│ │ @@ -2,14 +2,19 @@
│ │ from contextlib import contextmanager
│ │ import zlib
│ │ import io
│ │ import logging
│ │ from socket import timeout as SocketTimeout
│ │ from socket import error as SocketError
│ │
│ │ +try:
│ │ + import brotli
│ │ +except ImportError:
│ │ + brotli = None
│ │ +
│ │ from ._collections import HTTPHeaderDict
│ │ from .exceptions import (
│ │ BodyNotHttplibCompatible, ProtocolError, DecodeError, ReadTimeoutError,
│ │ ResponseNotChunked, IncompleteRead, InvalidHeader
│ │ )
│ │ from .packages.six import string_types as basestring, PY3
│ │ from .packages.six.moves import http_client as httplib
│ │ @@ -86,14 +91,33 @@
│ │ data = self._obj.unused_data
│ │ if not data:
│ │ return bytes(ret)
│ │ self._state = GzipDecoderState.OTHER_MEMBERS
│ │ self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS)
│ │
│ │
│ │ +if brotli is not None:
│ │ + class BrotliDecoder(object):
│ │ + # Supports both 'brotlipy' and 'Brotli' packages
│ │ + # since they share an import name. The top branches
│ │ + # are for 'brotlipy' and bottom branches for 'Brotli'
│ │ + def __init__(self):
│ │ + self._obj = brotli.Decompressor()
│ │ +
│ │ + def decompress(self, data):
│ │ + if hasattr(self._obj, 'decompress'):
│ │ + return self._obj.decompress(data)
│ │ + return self._obj.process(data)
│ │ +
│ │ + def flush(self):
│ │ + if hasattr(self._obj, 'flush'):
│ │ + return self._obj.flush()
│ │ + return b''
│ │ +
│ │ +
│ │ class MultiDecoder(object):
│ │ """
│ │ From RFC7231:
│ │ If one or more encodings have been applied to a representation, the
│ │ sender that applied the encodings MUST generate a Content-Encoding
│ │ header field that lists the content codings in the order in which
│ │ they were applied.
│ │ @@ -114,14 +138,17 @@
│ │ def _get_decoder(mode):
│ │ if ',' in mode:
│ │ return MultiDecoder(mode)
│ │
│ │ if mode == 'gzip':
│ │ return GzipDecoder()
│ │
│ │ + if brotli is not None and mode == 'br':
│ │ + return BrotliDecoder()
│ │ +
│ │ return DeflateDecoder()
│ │
│ │
│ │ class HTTPResponse(io.IOBase):
│ │ """
│ │ HTTP Response container.
│ │
│ │ @@ -151,14 +178,16 @@
│ │
│ │ :param enforce_content_length:
│ │ Enforce content length checking. Body returned by server must match
│ │ value of Content-Length header, if present. Otherwise, raise error.
│ │ """
│ │
│ │ CONTENT_DECODERS = ['gzip', 'deflate']
│ │ + if brotli is not None:
│ │ + CONTENT_DECODERS += ['br']
│ │ REDIRECT_STATUSES = [301, 302, 303, 307, 308]
│ │
│ │ def __init__(self, body='', headers=None, status=0, version=0, reason=None,
│ │ strict=0, preload_content=True, decode_content=True,
│ │ original_response=None, pool=None, connection=None, msg=None,
│ │ retries=None, enforce_content_length=False,
│ │ request_method=None, request_url=None):
│ │ @@ -307,32 +336,40 @@
│ │ # Note: content-encoding value should be case-insensitive, per RFC 7230
│ │ # Section 3.2
│ │ content_encoding = self.headers.get('content-encoding', '').lower()
│ │ if self._decoder is None:
│ │ if content_encoding in self.CONTENT_DECODERS:
│ │ self._decoder = _get_decoder(content_encoding)
│ │ elif ',' in content_encoding:
│ │ - encodings = [e.strip() for e in content_encoding.split(',') if e.strip() in self.CONTENT_DECODERS]
│ │ + encodings = [
│ │ + e.strip() for e in content_encoding.split(',')
│ │ + if e.strip() in self.CONTENT_DECODERS]
│ │ if len(encodings):
│ │ self._decoder = _get_decoder(content_encoding)
│ │
│ │ + DECODER_ERROR_CLASSES = (IOError, zlib.error)
│ │ + if brotli is not None:
│ │ + DECODER_ERROR_CLASSES += (brotli.error,)
│ │ +
│ │ def _decode(self, data, decode_content, flush_decoder):
│ │ """
│ │ Decode the data passed in and potentially flush the decoder.
│ │ """
│ │ + if not decode_content:
│ │ + return data
│ │ +
│ │ try:
│ │ - if decode_content and self._decoder:
│ │ + if self._decoder:
│ │ data = self._decoder.decompress(data)
│ │ - except (IOError, zlib.error) as e:
│ │ + except self.DECODER_ERROR_CLASSES as e:
│ │ content_encoding = self.headers.get('content-encoding', '').lower()
│ │ raise DecodeError(
│ │ "Received response with content-encoding: %s, but "
│ │ "failed to decode it." % content_encoding, e)
│ │ -
│ │ - if flush_decoder and decode_content:
│ │ + if flush_decoder:
│ │ data += self._flush_decoder()
│ │
│ │ return data
│ │
│ │ def _flush_decoder(self):
│ │ """
│ │ Flushes the decoder. Should only be called if the decoder is actually
│ │ @@ -504,17 +541,18 @@
│ │
│ │ Remaining parameters are passed to the HTTPResponse constructor, along
│ │ with ``original_response=r``.
│ │ """
│ │ headers = r.msg
│ │
│ │ if not isinstance(headers, HTTPHeaderDict):
│ │ - if PY3: # Python 3
│ │ + if PY3:
│ │ headers = HTTPHeaderDict(headers.items())
│ │ - else: # Python 2
│ │ + else:
│ │ + # Python 2.7
│ │ headers = HTTPHeaderDict.from_httplib(headers)
│ │
│ │ # HTTPResponse objects in Python 3 don't have a .strict attribute
│ │ strict = getattr(r, 'strict', 0)
│ │ resp = ResponseCls(body=r,
│ │ headers=headers,
│ │ status=r.status,
│ │ @@ -699,7 +737,24 @@
│ │ If the request that generated this response redirected, this method
│ │ will return the final redirect location.
│ │ """
│ │ if self.retries is not None and len(self.retries.history):
│ │ return self.retries.history[-1].redirect_location
│ │ else:
│ │ return self._request_url
│ │ +
│ │ + def __iter__(self):
│ │ + buffer = [b""]
│ │ + for chunk in self.stream(decode_content=True):
│ │ + if b"\n" in chunk:
│ │ + chunk = chunk.split(b"\n")
│ │ + yield b"".join(buffer) + chunk[0] + b"\n"
│ │ + for x in chunk[1:-1]:
│ │ + yield x + b"\n"
│ │ + if chunk[-1]:
│ │ + buffer = [chunk[-1]]
│ │ + else:
│ │ + buffer = []
│ │ + else:
│ │ + buffer.append(chunk)
│ │ + if buffer:
│ │ + yield b"".join(buffer)
│ --- urllib3-1.24.1/docs/advanced-usage.rst
├── +++ urllib3-1.25.3/docs/advanced-usage.rst
│┄ Files similar despite different names (difference score: 27)
│ │ @@ -135,16 +135,16 @@
│ │ >>> from urllib3.contrib.socks import SOCKSProxyManager
│ │ >>> proxy = SOCKSProxyManager('socks5://localhost:8889/')
│ │ >>> proxy.request('GET', 'http://google.com/')
│ │
│ │
│ │ .. _ssl_custom:
│ │
│ │ -Custom SSL certificates and client certificates
│ │ ------------------------------------------------
│ │ +Custom SSL certificates
│ │ +-----------------------
│ │
│ │ Instead of using `certifi <https://certifi.io/>`_ you can provide your
│ │ own certificate authority bundle. This is useful for cases where you've
│ │ generated your own certificates or when you're using a private certificate
│ │ authority. Just provide the full path to the certificate bundle when creating a
│ │ :class:`~poolmanager.PoolManager`::
│ │
│ │ @@ -154,24 +154,40 @@
│ │ ... ca_certs='/path/to/your/certificate_bundle')
│ │
│ │ When you specify your own certificate bundle only requests that can be
│ │ verified with that bundle will succeed. It's recommended to use a separate
│ │ :class:`~poolmanager.PoolManager` to make requests to URLs that do not need
│ │ the custom certificate.
│ │
│ │ +.. _ssl_client:
│ │ +
│ │ +Client certificates
│ │ +-------------------
│ │ +
│ │ You can also specify a client certificate. This is useful when both the server
│ │ and the client need to verify each other's identity. Typically these
│ │ certificates are issued from the same authority. To use a client certificate,
│ │ provide the full path when creating a :class:`~poolmanager.PoolManager`::
│ │
│ │ >>> http = urllib3.PoolManager(
│ │ ... cert_file='/path/to/your/client_cert.pem',
│ │ ... cert_reqs='CERT_REQUIRED',
│ │ ... ca_certs='/path/to/your/certificate_bundle')
│ │
│ │ +If you have an encrypted client certificate private key you can use
│ │ +the ``key_password`` parameter to specify a password to decrypt the key. ::
│ │ +
│ │ + >>> http = urllib3.PoolManager(
│ │ + ... cert_file='/path/to/your/client_cert.pem',
│ │ + ... cert_reqs='CERT_REQUIRED',
│ │ + ... key_file='/path/to/your/client.key',
│ │ + ... key_password='keyfile_password')
│ │ +
│ │ +If your key isn't encrypted the ``key_password`` parameter isn't required.
│ │ +
│ │ .. _ssl_mac:
│ │
│ │ Certificate validation and Mac OS X
│ │ -----------------------------------
│ │
│ │ Apple-provided Python and OpenSSL libraries contain a patches that make them
│ │ automatically check the system keychain's certificates. This can be
│ │ @@ -186,15 +202,15 @@
│ │
│ │ .. _ssl_warnings:
│ │
│ │ SSL Warnings
│ │ ------------
│ │
│ │ urllib3 will issue several different warnings based on the level of certificate
│ │ -verification support. These warning indicate particular situations and can
│ │ +verification support. These warnings indicate particular situations and can
│ │ be resolved in different ways.
│ │
│ │ * :class:`~exceptions.InsecureRequestWarning`
│ │ This happens when a request is made to an HTTPS URL without certificate
│ │ verification enabled. Follow the :ref:`certificate verification <ssl>`
│ │ guide to resolve this warning.
│ │ * :class:`~exceptions.InsecurePlatformWarning`
│ │ @@ -253,7 +269,23 @@
│ │ :class:`~urllib3.poolmanager.PoolManager` as usual::
│ │
│ │ env_variables:
│ │ GAE_USE_SOCKETS_HTTPLIB : 'true'
│ │
│ │ For more details on the limitations and gotchas, see
│ │ :mod:`urllib3.contrib.appengine`.
│ │ +
│ │ +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.
│ │ +You may also request the package be installed via the ``urllib3[brotli]`` extra::
│ │ +
│ │ + python -m pip install urllib3[brotli]
│ │ +
│ │ +Here's an example using brotli encoding via the ``Accept-Encoding`` header::
│ │ +
│ │ + >>> from urllib3 import PoolManager
│ │ + >>> http = PoolManager()
│ │ + >>> http.request('GET', 'https://www.google.com/', headers={'Accept-Encoding': 'br'})
│ --- urllib3-1.24.1/test/test_proxymanager.py
├── +++ urllib3-1.25.3/test/test_proxymanager.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/docs/index.rst
├── +++ urllib3-1.25.3/docs/index.rst
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/with_dummyserver/test_https.py
├── +++ urllib3-1.25.3/test/with_dummyserver/test_https.py
│┄ Files similar despite different names (difference score: 15)
│ │ @@ -13,26 +13,33 @@
│ │ HTTPSDummyServerTestCase, IPV6HTTPSDummyServerTestCase
│ │ )
│ │ from dummyserver.server import (DEFAULT_CA, DEFAULT_CA_BAD, DEFAULT_CERTS,
│ │ DEFAULT_CLIENT_CERTS,
│ │ DEFAULT_CLIENT_NO_INTERMEDIATE_CERTS,
│ │ NO_SAN_CERTS, NO_SAN_CA, DEFAULT_CA_DIR,
│ │ IPV6_ADDR_CERTS, IPV6_ADDR_CA, HAS_IPV6,
│ │ - IP_SAN_CERTS)
│ │ + IP_SAN_CERTS, IPV6_SAN_CERTS, IPV6_SAN_CA,
│ │ + PASSWORD_CLIENT_KEYFILE)
│ │
│ │ from test import (
│ │ onlyPy279OrNewer,
│ │ notSecureTransport,
│ │ + notOpenSSL098,
│ │ requires_network,
│ │ + requires_ssl_context_keyfile_password,
│ │ + fails_on_travis_gce,
│ │ + requiresTLSv1,
│ │ + requiresTLSv1_1,
│ │ + requiresTLSv1_2,
│ │ + requiresTLSv1_3,
│ │ TARPIT_HOST,
│ │ )
│ │ from urllib3 import HTTPSConnectionPool
│ │ from urllib3.connection import (
│ │ VerifiedHTTPSConnection,
│ │ - UnverifiedHTTPSConnection,
│ │ RECENT_DATE,
│ │ )
│ │ from urllib3.exceptions import (
│ │ SSLError,
│ │ ConnectTimeoutError,
│ │ InsecureRequestWarning,
│ │ SystemTimeWarning,
│ │ @@ -51,54 +58,64 @@
│ │
│ │
│ │ log = logging.getLogger('urllib3.connectionpool')
│ │ log.setLevel(logging.NOTSET)
│ │ log.addHandler(logging.StreamHandler(sys.stdout))
│ │
│ │
│ │ +TLSv1_CERTS = DEFAULT_CERTS.copy()
│ │ +TLSv1_CERTS["ssl_version"] = getattr(ssl, "PROTOCOL_TLSv1", None)
│ │ +
│ │ +TLSv1_1_CERTS = DEFAULT_CERTS.copy()
│ │ +TLSv1_1_CERTS["ssl_version"] = getattr(ssl, "PROTOCOL_TLSv1_1", None)
│ │ +
│ │ +TLSv1_2_CERTS = DEFAULT_CERTS.copy()
│ │ +TLSv1_2_CERTS["ssl_version"] = getattr(ssl, "PROTOCOL_TLSv1_2", None)
│ │ +
│ │ +
│ │ class TestHTTPS(HTTPSDummyServerTestCase):
│ │ + tls_protocol_name = None
│ │ +
│ │ def setUp(self):
│ │ - self._pool = HTTPSConnectionPool(self.host, self.port)
│ │ + self._pool = HTTPSConnectionPool(self.host, self.port, ca_certs=DEFAULT_CA)
│ │ self.addCleanup(self._pool.close)
│ │
│ │ def test_simple(self):
│ │ r = self._pool.request('GET', '/')
│ │ self.assertEqual(r.status, 200, r.data)
│ │
│ │ + @fails_on_travis_gce
│ │ def test_dotted_fqdn(self):
│ │ - pool = HTTPSConnectionPool(self.host + '.', self.port)
│ │ + pool = HTTPSConnectionPool(self.host + '.', self.port, ca_certs=DEFAULT_CA)
│ │ r = pool.request('GET', '/')
│ │ self.assertEqual(r.status, 200, r.data)
│ │
│ │ - def test_set_ssl_version_to_tlsv1(self):
│ │ - self._pool.ssl_version = ssl.PROTOCOL_TLSv1
│ │ - r = self._pool.request('GET', '/')
│ │ - self.assertEqual(r.status, 200, r.data)
│ │ -
│ │ def test_client_intermediate(self):
│ │ client_cert, client_key = (
│ │ DEFAULT_CLIENT_CERTS['certfile'],
│ │ DEFAULT_CLIENT_CERTS['keyfile'],
│ │ )
│ │ https_pool = HTTPSConnectionPool(self.host, self.port,
│ │ key_file=client_key,
│ │ - cert_file=client_cert)
│ │ + cert_file=client_cert,
│ │ + ca_certs=DEFAULT_CA)
│ │ r = https_pool.request('GET', '/certificate')
│ │ subject = json.loads(r.data.decode('utf-8'))
│ │ assert subject['organizationalUnitName'].startswith(
│ │ 'Testing server cert')
│ │
│ │ def test_client_no_intermediate(self):
│ │ client_cert, client_key = (
│ │ DEFAULT_CLIENT_NO_INTERMEDIATE_CERTS['certfile'],
│ │ DEFAULT_CLIENT_NO_INTERMEDIATE_CERTS['keyfile']
│ │ )
│ │ https_pool = HTTPSConnectionPool(self.host, self.port,
│ │ cert_file=client_cert,
│ │ - key_file=client_key)
│ │ + key_file=client_key,
│ │ + ca_certs=DEFAULT_CA)
│ │ try:
│ │ https_pool.request('GET', '/certificate', retries=False)
│ │ except SSLError as e:
│ │ if not ('alert unknown ca' in str(e) or
│ │ 'invalid certificate chain' in str(e) or
│ │ 'unknown Cert Authority' in str(e) or
│ │ # https://github.com/urllib3/urllib3/issues/1422
│ │ @@ -106,14 +123,47 @@
│ │ 'WSAECONNRESET' in str(e)):
│ │ raise
│ │ except ProtocolError as e:
│ │ # https://github.com/urllib3/urllib3/issues/1422
│ │ if not ('An existing connection was forcibly closed by the remote host' in str(e)):
│ │ raise
│ │
│ │ + @requires_ssl_context_keyfile_password
│ │ + def test_client_key_password(self):
│ │ + client_cert, client_key = (
│ │ + DEFAULT_CLIENT_CERTS['certfile'],
│ │ + PASSWORD_CLIENT_KEYFILE,
│ │ + )
│ │ + https_pool = HTTPSConnectionPool(self.host, self.port,
│ │ + ca_certs=DEFAULT_CA,
│ │ + key_file=client_key,
│ │ + cert_file=client_cert,
│ │ + key_password="letmein")
│ │ + r = https_pool.request('GET', '/certificate')
│ │ + subject = json.loads(r.data.decode('utf-8'))
│ │ + assert subject['organizationalUnitName'].startswith(
│ │ + 'Testing server cert')
│ │ +
│ │ + @requires_ssl_context_keyfile_password
│ │ + def test_client_encrypted_key_requires_password(self):
│ │ + client_cert, client_key = (
│ │ + DEFAULT_CLIENT_CERTS['certfile'],
│ │ + PASSWORD_CLIENT_KEYFILE,
│ │ + )
│ │ + https_pool = HTTPSConnectionPool(self.host, self.port,
│ │ + key_file=client_key,
│ │ + cert_file=client_cert,
│ │ + key_password=None)
│ │ +
│ │ + with pytest.raises(MaxRetryError) as e:
│ │ + https_pool.request('GET', '/certificate')
│ │ +
│ │ + assert 'password is required' in str(e.value)
│ │ + assert isinstance(e.value.reason, SSLError)
│ │ +
│ │ def test_verified(self):
│ │ https_pool = HTTPSConnectionPool(self.host, self.port,
│ │ cert_reqs='CERT_REQUIRED',
│ │ ca_certs=DEFAULT_CA)
│ │ self.addCleanup(https_pool.close)
│ │
│ │ conn = https_pool._new_conn()
│ │ @@ -191,14 +241,15 @@
│ │ else:
│ │ call = warn.call_args_list[1]
│ │ error = call[0][1]
│ │ self.assertEqual(error, InsecurePlatformWarning)
│ │
│ │ @onlyPy279OrNewer
│ │ @notSecureTransport # SecureTransport does not support cert directories
│ │ + @notOpenSSL098 # OpenSSL 0.9.8 does not support cert directories
│ │ def test_ca_dir_verified(self):
│ │ https_pool = HTTPSConnectionPool(self.host, self.port,
│ │ cert_reqs='CERT_REQUIRED',
│ │ ca_cert_dir=DEFAULT_CA_DIR)
│ │ self.addCleanup(https_pool.close)
│ │
│ │ conn = https_pool._new_conn()
│ │ @@ -269,16 +320,15 @@
│ │ self.assertRaises(SSLError, pool._new_conn)
│ │ with self.assertRaises(MaxRetryError) as cm:
│ │ pool.request('GET', '/', retries=0)
│ │ self.assertIsInstance(cm.exception.reason, SSLError)
│ │
│ │ def test_unverified_ssl(self):
│ │ """ Test that bare HTTPSConnection can connect, make requests """
│ │ - pool = HTTPSConnectionPool(self.host, self.port)
│ │ - pool.ConnectionCls = UnverifiedHTTPSConnection
│ │ + pool = HTTPSConnectionPool(self.host, self.port, cert_reqs=ssl.CERT_NONE)
│ │ self.addCleanup(pool.close)
│ │
│ │ with mock.patch('warnings.warn') as warn:
│ │ r = pool.request('GET', '/')
│ │ self.assertEqual(r.status, 200)
│ │ self.assertTrue(warn.called)
│ │
│ │ @@ -453,15 +503,15 @@
│ │ timeout = Timeout(total=None, connect=0.001)
│ │ https_pool = HTTPSConnectionPool(TARPIT_HOST, self.port,
│ │ timeout=timeout, retries=False,
│ │ cert_reqs='CERT_REQUIRED')
│ │ self.addCleanup(https_pool.close)
│ │ self.assertRaises(ConnectTimeoutError, https_pool.request, 'GET', '/')
│ │
│ │ - timeout = Timeout(read=0.001)
│ │ + timeout = Timeout(read=0.01)
│ │ https_pool = HTTPSConnectionPool(self.host, self.port,
│ │ timeout=timeout, retries=False,
│ │ cert_reqs='CERT_REQUIRED')
│ │ self.addCleanup(https_pool.close)
│ │ https_pool.ca_certs = DEFAULT_CA
│ │ https_pool.assert_fingerprint = '92:81:FE:85:F7:0C:26:60:EC:D6:B3:' \
│ │ 'BF:93:CF:F9:71:CC:07:7D:0A'
│ │ @@ -510,23 +560,22 @@
│ │ conn = https_pool._new_conn()
│ │ self.assertRaises(ConnectTimeoutError, https_pool.request, 'GET', '/',
│ │ timeout=Timeout(total=None, connect=0.001))
│ │
│ │ def test_enhanced_ssl_connection(self):
│ │ fingerprint = '92:81:FE:85:F7:0C:26:60:EC:D6:B3:BF:93:CF:F9:71:CC:07:7D:0A'
│ │
│ │ - conn = VerifiedHTTPSConnection(self.host, self.port)
│ │ - self.addCleanup(conn.close)
│ │ https_pool = HTTPSConnectionPool(self.host, self.port,
│ │ cert_reqs='CERT_REQUIRED',
│ │ ca_certs=DEFAULT_CA,
│ │ assert_fingerprint=fingerprint)
│ │ self.addCleanup(https_pool.close)
│ │
│ │ - https_pool._make_request(conn, 'GET', '/')
│ │ + r = https_pool.request('GET', '/')
│ │ + assert r.status == 200
│ │
│ │ @onlyPy279OrNewer
│ │ def test_ssl_correct_system_time(self):
│ │ self._pool.cert_reqs = 'CERT_REQUIRED'
│ │ self._pool.ca_certs = DEFAULT_CA
│ │
│ │ w = self._request_without_resource_warnings('GET', '/')
│ │ @@ -550,35 +599,61 @@
│ │ def _request_without_resource_warnings(self, method, url):
│ │ with warnings.catch_warnings(record=True) as w:
│ │ warnings.simplefilter('always')
│ │ self._pool.request(method, url)
│ │
│ │ return [x for x in w if not isinstance(x.message, ResourceWarning)]
│ │
│ │ + def test_set_ssl_version_to_tls_version(self):
│ │ + if self.tls_protocol_name is None:
│ │ + pytest.skip("Skipping base test class")
│ │
│ │ -class TestHTTPS_TLSv1(HTTPSDummyServerTestCase):
│ │ - certs = DEFAULT_CERTS.copy()
│ │ - certs['ssl_version'] = ssl.PROTOCOL_TLSv1
│ │ -
│ │ - def setUp(self):
│ │ - self._pool = HTTPSConnectionPool(self.host, self.port)
│ │ - self.addCleanup(self._pool.close)
│ │ -
│ │ - def test_discards_connection_on_sslerror(self):
│ │ - self._pool.cert_reqs = 'CERT_REQUIRED'
│ │ - with self.assertRaises(MaxRetryError) as cm:
│ │ - self._pool.request('GET', '/', retries=0)
│ │ - self.assertIsInstance(cm.exception.reason, SSLError)
│ │ - self._pool.ca_certs = DEFAULT_CA
│ │ - self._pool.request('GET', '/')
│ │ + self._pool.ssl_version = self.certs['ssl_version']
│ │ + r = self._pool.request('GET', '/')
│ │ + self.assertEqual(r.status, 200, r.data)
│ │
│ │ def test_set_cert_default_cert_required(self):
│ │ conn = VerifiedHTTPSConnection(self.host, self.port)
│ │ - conn.set_cert(ca_certs=DEFAULT_CA)
│ │ - self.assertEqual(conn.cert_reqs, 'CERT_REQUIRED')
│ │ + conn.set_cert()
│ │ + self.assertEqual(conn.cert_reqs, ssl.CERT_REQUIRED)
│ │ +
│ │ + def test_tls_protocol_name_of_socket(self):
│ │ + if self.tls_protocol_name is None:
│ │ + pytest.skip("Skipping base test class")
│ │ +
│ │ + conn = self._pool._get_conn()
│ │ + conn.connect()
│ │ +
│ │ + if not hasattr(conn.sock, 'version'):
│ │ + pytest.skip('SSLSocket.version() not available')
│ │ +
│ │ + self.assertEqual(conn.sock.version(), self.tls_protocol_name)
│ │ +
│ │ +
│ │ +@requiresTLSv1()
│ │ +class TestHTTPS_TLSv1(TestHTTPS):
│ │ + tls_protocol_name = 'TLSv1'
│ │ + certs = TLSv1_CERTS
│ │ +
│ │ +
│ │ +@requiresTLSv1_1()
│ │ +class TestHTTPS_TLSv1_1(TestHTTPS):
│ │ + tls_protocol_name = 'TLSv1.1'
│ │ + certs = TLSv1_1_CERTS
│ │ +
│ │ +
│ │ +@requiresTLSv1_2()
│ │ +class TestHTTPS_TLSv1_2(TestHTTPS):
│ │ + tls_protocol_name = 'TLSv1.2'
│ │ + certs = TLSv1_2_CERTS
│ │ +
│ │ +
│ │ +@requiresTLSv1_3()
│ │ +class TestHTTPS_TLSv1_3(TestHTTPS):
│ │ + tls_protocol_name = 'TLSv1.3'
│ │
│ │
│ │ class TestHTTPS_NoSAN(HTTPSDummyServerTestCase):
│ │ certs = NO_SAN_CERTS
│ │
│ │ def test_warning_for_certs_without_a_san(self):
│ │ """Ensure that a warning is raised when the cert from the server has
│ │ @@ -621,9 +696,27 @@
│ │ cert_reqs='CERT_REQUIRED',
│ │ ca_certs=IPV6_ADDR_CA)
│ │ self.addCleanup(https_pool.close)
│ │ r = https_pool.request('GET', '/')
│ │ self.assertEqual(r.status, 200)
│ │
│ │
│ │ +class TestHTTPS_IPV6SAN(IPV6HTTPSDummyServerTestCase):
│ │ + certs = IPV6_SAN_CERTS
│ │ +
│ │ + def test_can_validate_ipv6_san(self):
│ │ + """Ensure that urllib3 can validate SANs with IPv6 addresses in them."""
│ │ + try:
│ │ + import ipaddress # noqa: F401
│ │ + except ImportError:
│ │ + pytest.skip("Only runs on systems with an ipaddress module")
│ │ +
│ │ + https_pool = HTTPSConnectionPool('[::1]', self.port,
│ │ + cert_reqs='CERT_REQUIRED',
│ │ + ca_certs=IPV6_SAN_CA)
│ │ + self.addCleanup(https_pool.close)
│ │ + r = https_pool.request('GET', '/')
│ │ + self.assertEqual(r.status, 200)
│ │ +
│ │ +
│ │ if __name__ == '__main__':
│ │ unittest.main()
│ --- urllib3-1.24.1/test/port_helpers.py
├── +++ urllib3-1.25.3/test/port_helpers.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/client.pem
├── +++ urllib3-1.25.3/dummyserver/certs/client.pem
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/ca_path_test/b6b9ccf9.0
├── +++ urllib3-1.25.3/dummyserver/certs/ca_path_test/cacert.pem
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/contrib/securetransport.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/securetransport.py
│┄ Files similar despite different names (difference score: 14)
│ │ @@ -19,14 +19,39 @@
│ │
│ │ To use this module, simply import and inject it::
│ │
│ │ import urllib3.contrib.securetransport
│ │ urllib3.contrib.securetransport.inject_into_urllib3()
│ │
│ │ Happy TLSing!
│ │ +
│ │ +This code is a bastardised version of the code found in Will Bond's oscrypto
│ │ +library. An enormous debt is owed to him for blazing this trail for us. For
│ │ +that reason, this code should be considered to be covered both by urllib3's
│ │ +license and by oscrypto's:
│ │ +
│ │ + Copyright (c) 2015-2016 Will Bond <[email protected]>
│ │ +
│ │ + Permission is hereby granted, free of charge, to any person obtaining a
│ │ + copy of this software and associated documentation files (the "Software"),
│ │ + to deal in the Software without restriction, including without limitation
│ │ + the rights to use, copy, modify, merge, publish, distribute, sublicense,
│ │ + and/or sell copies of the Software, and to permit persons to whom the
│ │ + Software is furnished to do so, subject to the following conditions:
│ │ +
│ │ + The above copyright notice and this permission notice shall be included in
│ │ + all copies or substantial portions of the Software.
│ │ +
│ │ + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
│ │ + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
│ │ + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
│ │ + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
│ │ + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
│ │ + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
│ │ + DEALINGS IN THE SOFTWARE.
│ │ """
│ │ from __future__ import absolute_import
│ │
│ │ import contextlib
│ │ import ctypes
│ │ import errno
│ │ import os.path
│ │ @@ -82,53 +107,51 @@
│ │ # for no better reason than we need *a* limit, and this one is right there.
│ │ SSL_WRITE_BLOCKSIZE = 16384
│ │
│ │ # This is our equivalent of util.ssl_.DEFAULT_CIPHERS, but expanded out to
│ │ # individual cipher suites. We need to do this because this is how
│ │ # SecureTransport wants them.
│ │ CIPHER_SUITES = [
│ │ - SecurityConst.TLS_AES_256_GCM_SHA384,
│ │ - SecurityConst.TLS_CHACHA20_POLY1305_SHA256,
│ │ - SecurityConst.TLS_AES_128_GCM_SHA256,
│ │ SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
│ │ - SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
│ │ SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
│ │ + SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
│ │ SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
│ │ - SecurityConst.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,
│ │ + SecurityConst.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
│ │ + SecurityConst.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
│ │ SecurityConst.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
│ │ - SecurityConst.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
│ │ SecurityConst.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
│ │ SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
│ │ - SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
│ │ SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
│ │ - SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
│ │ - SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
│ │ - SecurityConst.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
│ │ - SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
│ │ - SecurityConst.TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
│ │ SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
│ │ - SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
│ │ SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
│ │ + SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
│ │ + SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
│ │ + SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
│ │ SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
│ │ + SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
│ │ + SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
│ │ SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
│ │ - SecurityConst.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
│ │ SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
│ │ - SecurityConst.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
│ │ + SecurityConst.TLS_AES_256_GCM_SHA384,
│ │ + SecurityConst.TLS_AES_128_GCM_SHA256,
│ │ SecurityConst.TLS_RSA_WITH_AES_256_GCM_SHA384,
│ │ SecurityConst.TLS_RSA_WITH_AES_128_GCM_SHA256,
│ │ + SecurityConst.TLS_AES_128_CCM_8_SHA256,
│ │ + SecurityConst.TLS_AES_128_CCM_SHA256,
│ │ SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA256,
│ │ SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA256,
│ │ SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA,
│ │ SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA,
│ │ ]
│ │
│ │ # Basically this is simple: for PROTOCOL_SSLv23 we turn it into a low of
│ │ -# TLSv1 and a high of TLSv1.2. For everything else, we pin to that version.
│ │ +# TLSv1 and a high of TLSv1.3. For everything else, we pin to that version.
│ │ +# TLSv1 to 1.2 are supported on macOS 10.8+ and TLSv1.3 is macOS 10.13+
│ │ _protocol_to_min_max = {
│ │ - ssl.PROTOCOL_SSLv23: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol12),
│ │ + util.PROTOCOL_TLS: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocolMaxSupported),
│ │ }
│ │
│ │ if hasattr(ssl, "PROTOCOL_SSLv2"):
│ │ _protocol_to_min_max[ssl.PROTOCOL_SSLv2] = (
│ │ SecurityConst.kSSLProtocol2, SecurityConst.kSSLProtocol2
│ │ )
│ │ if hasattr(ssl, "PROTOCOL_SSLv3"):
│ │ @@ -143,33 +166,33 @@
│ │ _protocol_to_min_max[ssl.PROTOCOL_TLSv1_1] = (
│ │ SecurityConst.kTLSProtocol11, SecurityConst.kTLSProtocol11
│ │ )
│ │ if hasattr(ssl, "PROTOCOL_TLSv1_2"):
│ │ _protocol_to_min_max[ssl.PROTOCOL_TLSv1_2] = (
│ │ SecurityConst.kTLSProtocol12, SecurityConst.kTLSProtocol12
│ │ )
│ │ -if hasattr(ssl, "PROTOCOL_TLS"):
│ │ - _protocol_to_min_max[ssl.PROTOCOL_TLS] = _protocol_to_min_max[ssl.PROTOCOL_SSLv23]
│ │
│ │
│ │ def inject_into_urllib3():
│ │ """
│ │ Monkey-patch urllib3 with SecureTransport-backed SSL-support.
│ │ """
│ │ + util.SSLContext = SecureTransportContext
│ │ util.ssl_.SSLContext = SecureTransportContext
│ │ util.HAS_SNI = HAS_SNI
│ │ util.ssl_.HAS_SNI = HAS_SNI
│ │ util.IS_SECURETRANSPORT = True
│ │ util.ssl_.IS_SECURETRANSPORT = True
│ │
│ │
│ │ def extract_from_urllib3():
│ │ """
│ │ Undo monkey-patching by :func:`inject_into_urllib3`.
│ │ """
│ │ + util.SSLContext = orig_util_SSLContext
│ │ util.ssl_.SSLContext = orig_util_SSLContext
│ │ util.HAS_SNI = orig_util_HAS_SNI
│ │ util.ssl_.HAS_SNI = orig_util_HAS_SNI
│ │ util.IS_SECURETRANSPORT = False
│ │ util.ssl_.IS_SECURETRANSPORT = False
│ │
│ │
│ │ @@ -454,15 +477,22 @@
│ │
│ │ # Setup the ciphers.
│ │ self._set_ciphers()
│ │
│ │ # Set the minimum and maximum TLS versions.
│ │ result = Security.SSLSetProtocolVersionMin(self.context, min_version)
│ │ _assert_no_error(result)
│ │ +
│ │ + # TLS 1.3 isn't necessarily enabled by the OS
│ │ + # so we have to detect when we error out and try
│ │ + # setting TLS 1.3 if it's allowed. kTLSProtocolMaxSupported
│ │ + # was added in macOS 10.13 along with kTLSProtocol13.
│ │ result = Security.SSLSetProtocolVersionMax(self.context, max_version)
│ │ + if result != 0 and max_version == SecurityConst.kTLSProtocolMaxSupported:
│ │ + result = Security.SSLSetProtocolVersionMax(self.context, SecurityConst.kTLSProtocol12)
│ │ _assert_no_error(result)
│ │
│ │ # If there's a trust DB, we need to use it. We do that by telling
│ │ # SecureTransport to break on server auth. We also do that if we don't
│ │ # want to validate the certs at all: we just won't actually do any
│ │ # authing in that case.
│ │ if not verify or trust_bundle is not None:
│ │ @@ -663,14 +693,33 @@
│ │ if certdata:
│ │ CoreFoundation.CFRelease(certdata)
│ │ if trust:
│ │ CoreFoundation.CFRelease(trust)
│ │
│ │ return der_bytes
│ │
│ │ + def version(self):
│ │ + protocol = Security.SSLProtocol()
│ │ + result = Security.SSLGetNegotiatedProtocolVersion(self.context, ctypes.byref(protocol))
│ │ + _assert_no_error(result)
│ │ + if protocol.value == SecurityConst.kTLSProtocol13:
│ │ + return 'TLSv1.3'
│ │ + elif protocol.value == SecurityConst.kTLSProtocol12:
│ │ + return 'TLSv1.2'
│ │ + elif protocol.value == SecurityConst.kTLSProtocol11:
│ │ + return 'TLSv1.1'
│ │ + elif protocol.value == SecurityConst.kTLSProtocol1:
│ │ + return 'TLSv1'
│ │ + elif protocol.value == SecurityConst.kSSLProtocol3:
│ │ + return 'SSLv3'
│ │ + elif protocol.value == SecurityConst.kSSLProtocol2:
│ │ + return 'SSLv2'
│ │ + else:
│ │ + raise ssl.SSLError('Unknown TLS version: %r' % protocol)
│ │ +
│ │ def _reuse(self):
│ │ self._makefile_refs += 1
│ │
│ │ def _drop(self):
│ │ if self._makefile_refs < 1:
│ │ self.close()
│ │ else:
│ --- urllib3-1.24.1/src/urllib3/exceptions.py
├── +++ urllib3-1.25.3/src/urllib3/exceptions.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3.egg-info/PKG-INFO
├── +++ urllib3-1.25.3/src/urllib3.egg-info/PKG-INFO
│┄ Files similar despite different names (difference score: 7)
│ │ @@ -1,10 +1,10 @@
│ │ Metadata-Version: 2.1
│ │ Name: urllib3
│ │ -Version: 1.24.1
│ │ +Version: 1.25.3
│ │ Summary: HTTP library with thread-safe connection pooling, file post, and more.
│ │ Home-page: https://urllib3.readthedocs.io/
│ │ Author: Andrey Petrov
│ │ Author-email: [email protected]
│ │ License: MIT
│ │ Description: urllib3
│ │ =======
│ │ @@ -25,33 +25,33 @@
│ │ :alt: Coverage Status
│ │ :target: https://codecov.io/gh/urllib3/urllib3
│ │
│ │ .. image:: https://img.shields.io/pypi/v/urllib3.svg?maxAge=86400
│ │ :alt: PyPI version
│ │ :target: https://pypi.org/project/urllib3/
│ │
│ │ - .. image:: https://www.bountysource.com/badge/tracker?tracker_id=192525
│ │ - :alt: Bountysource
│ │ - :target: https://www.bountysource.com/trackers/192525-urllib3?utm_source=192525&utm_medium=shield&utm_campaign=TRACKER_BADGE
│ │ -
│ │ .. image:: https://badges.gitter.im/python-urllib3/Lobby.svg
│ │ :alt: Gitter
│ │ :target: https://gitter.im/python-urllib3/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
│ │
│ │ + .. image:: https://tidelift.com/badges/github/urllib3/urllib3
│ │ + :alt: Tidelift Dependencies
│ │ + :target: https://tidelift.com/subscription/pkg/pypi-urllib3?utm_source=pypi-urllib3&utm_medium=referral&utm_campaign=docs
│ │ +
│ │ urllib3 is a powerful, *sanity-friendly* HTTP client for Python. Much of the
│ │ Python ecosystem already uses urllib3 and you should too.
│ │ urllib3 brings many critical features that are missing from the Python
│ │ standard libraries:
│ │
│ │ - Thread safety.
│ │ - Connection pooling.
│ │ - Client-side SSL/TLS verification.
│ │ - File uploads with multipart encoding.
│ │ - Helpers for retrying requests and dealing with HTTP redirects.
│ │ - - Support for gzip and deflate encoding.
│ │ + - Support for gzip, deflate, and brotli encoding.
│ │ - Proxy support for HTTP and SOCKS.
│ │ - 100% test coverage.
│ │
│ │ urllib3 is powerful and easy to use::
│ │
│ │ >>> import urllib3
│ │ >>> http = urllib3.PoolManager()
│ │ @@ -85,50 +85,143 @@
│ │ ------------
│ │
│ │ urllib3 happily accepts contributions. Please see our
│ │ `contributing documentation <https://urllib3.readthedocs.io/en/latest/contributing.html>`_
│ │ for some tips on getting started.
│ │
│ │
│ │ + Security Disclosures
│ │ + --------------------
│ │ +
│ │ + To report a security vulnerability, please use the
│ │ + `Tidelift security contact <https://tidelift.com/security>`_.
│ │ + Tidelift will coordinate the fix and disclosure with maintainers.
│ │ +
│ │ Maintainers
│ │ -----------
│ │
│ │ - `@theacodes <https://github.com/theacodes>`_ (Thea Flowers)
│ │ - - `@SethMichaelLarson <https://github.com/SethMichaelLarson>`_ (Seth M. Larson)
│ │ - - `@haikuginger <https://github.com/haikuginger>`_ (Jesse Shapiro)
│ │ + - `@sethmlarson <https://github.com/sethmlarson>`_ (Seth M. Larson)
│ │ + - `@haikuginger <https://github.com/haikuginger>`_ (Jess Shapiro)
│ │ - `@lukasa <https://github.com/lukasa>`_ (Cory Benfield)
│ │ - `@sigmavirus24 <https://github.com/sigmavirus24>`_ (Ian Cordasco)
│ │ - `@shazow <https://github.com/shazow>`_ (Andrey Petrov)
│ │
│ │ 👋
│ │
│ │
│ │ Sponsorship
│ │ -----------
│ │
│ │ + .. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White_small.png
│ │ + :width: 75
│ │ + :alt: Tidelift
│ │ +
│ │ + .. list-table::
│ │ + :widths: 10 100
│ │ +
│ │ + * - |tideliftlogo|
│ │ + - Professional support for urllib3 is available as part of the `Tidelift
│ │ + Subscription`_. Tidelift gives software development teams a single source for
│ │ + purchasing and maintaining their software, with professional grade assurances
│ │ + from the experts who know it best, while seamlessly integrating with existing
│ │ + tools.
│ │ +
│ │ + .. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-urllib3?utm_source=pypi-urllib3&utm_medium=referral&utm_campaign=readme
│ │ +
│ │ If your company benefits from this library, please consider `sponsoring its
│ │ - development <https://urllib3.readthedocs.io/en/latest/contributing.html#sponsorship>`_.
│ │ + development <https://urllib3.readthedocs.io/en/latest/contributing.html#sponsorship-project-grants>`_.
│ │
│ │ Sponsors include:
│ │
│ │ - Google Cloud Platform (2018-present), sponsors `@theacodes <https://github.com/theacodes>`_'s work on an ongoing basis
│ │ - - Abbott (2018-present), sponsors `@SethMichaelLarson <https://github.com/SethMichaelLarson>`_'s work on an ongoing basis
│ │ - - Akamai (2017-present), sponsors `@haikuginger <https://github.com/haikuginger>`_'s work on an ongoing basis
│ │ + - Abbott (2018-present), sponsors `@sethmlarson <https://github.com/sethmlarson>`_'s work on an ongoing basis
│ │ + - Akamai (2017-2018), sponsored `@haikuginger <https://github.com/haikuginger>`_'s work on urllib3
│ │ - Hewlett Packard Enterprise (2016-2017), sponsored `@Lukasa’s <https://github.com/Lukasa>`_ work on urllib3
│ │
│ │
│ │ Changes
│ │ =======
│ │
│ │ + 1.25.3 (2019-05-23)
│ │ + -------------------
│ │ +
│ │ + * Change ``HTTPSConnection`` to load system CA certificates
│ │ + when ``ca_certs``, ``ca_cert_dir``, and ``ssl_context`` are
│ │ + unspecified. (Pull #1608, Issue #1603)
│ │ +
│ │ + * Upgrade bundled rfc3986 to v1.3.2. (Pull #1609, Issue #1605)
│ │ +
│ │ +
│ │ + 1.25.2 (2019-04-28)
│ │ + -------------------
│ │ +
│ │ + * Change ``is_ipaddress`` to not detect IPvFuture addresses. (Pull #1583)
│ │ +
│ │ + * Change ``parse_url`` to percent-encode invalid characters within the
│ │ + path, query, and target components. (Pull #1586)
│ │ +
│ │ +
│ │ + 1.25.1 (2019-04-24)
│ │ + -------------------
│ │ +
│ │ + * Add support for Google's ``Brotli`` package. (Pull #1572, Pull #1579)
│ │ +
│ │ + * Upgrade bundled rfc3986 to v1.3.1 (Pull #1578)
│ │ +
│ │ +
│ │ + 1.25 (2019-04-22)
│ │ + -----------------
│ │ +
│ │ + * Require and validate certificates by default when using HTTPS (Pull #1507)
│ │ +
│ │ + * Upgraded ``urllib3.utils.parse_url()`` to be RFC 3986 compliant. (Pull #1487)
│ │ +
│ │ + * Added support for ``key_password`` for ``HTTPSConnectionPool`` to use
│ │ + encrypted ``key_file`` without creating your own ``SSLContext`` object. (Pull #1489)
│ │ +
│ │ + * Add TLSv1.3 support to CPython, pyOpenSSL, and SecureTransport ``SSLContext``
│ │ + implementations. (Pull #1496)
│ │ +
│ │ + * Switched the default multipart header encoder from RFC 2231 to HTML 5 working draft. (Issue #303, PR #1492)
│ │ +
│ │ + * Fixed issue where OpenSSL would block if an encrypted client private key was
│ │ + given and no password was given. Instead an ``SSLError`` is raised. (Pull #1489)
│ │ +
│ │ + * Added support for Brotli content encoding. It is enabled automatically if
│ │ + ``brotlipy`` package is installed which can be requested with
│ │ + ``urllib3[brotli]`` extra. (Pull #1532)
│ │ +
│ │ + * Drop ciphers using DSS key exchange from default TLS cipher suites.
│ │ + Improve default ciphers when using SecureTransport. (Pull #1496)
│ │ +
│ │ + * Implemented a more efficient ``HTTPResponse.__iter__()`` method. (Issue #1483)
│ │ +
│ │ + 1.24.3 (2019-05-01)
│ │ + -------------------
│ │ +
│ │ + * Apply fix for CVE-2019-9740. (Pull #1591)
│ │ +
│ │ + 1.24.2 (2019-04-17)
│ │ + -------------------
│ │ +
│ │ + * Don't load system certificates by default when any other ``ca_certs``, ``ca_certs_dir`` or
│ │ + ``ssl_context`` parameters are specified.
│ │ +
│ │ + * Remove Authorization header regardless of case when redirecting to cross-site. (Issue #1510)
│ │ +
│ │ + * Add support for IPv6 addresses in subjectAltName section of certificates. (Issue #1269)
│ │ +
│ │ +
│ │ 1.24.1 (2018-11-02)
│ │ -------------------
│ │
│ │ * Remove quadratic behavior within ``GzipDecoder.decompress()`` (Issue #1467)
│ │
│ │ - * Restored functionality of `ciphers` parameter for `create_urllib3_context()`. (Issue #1462)
│ │ + * Restored functionality of ``ciphers`` parameter for ``create_urllib3_context()``. (Issue #1462)
│ │
│ │
│ │ 1.24 (2018-10-16)
│ │ -----------------
│ │
│ │ * Allow key_server_hostname to be specified when initializing a PoolManager to allow custom SNI to be overridden. (Pull #1449)
│ │
│ │ @@ -1088,14 +1181,17 @@
│ │ Classifier: Programming Language :: Python
│ │ Classifier: Programming Language :: Python :: 2
│ │ Classifier: Programming Language :: Python :: 2.7
│ │ Classifier: Programming Language :: Python :: 3
│ │ Classifier: Programming Language :: Python :: 3.4
│ │ Classifier: Programming Language :: Python :: 3.5
│ │ Classifier: Programming Language :: Python :: 3.6
│ │ +Classifier: Programming Language :: Python :: 3.7
│ │ +Classifier: Programming Language :: Python :: 3.8
│ │ Classifier: Programming Language :: Python :: Implementation :: CPython
│ │ Classifier: Programming Language :: Python :: Implementation :: PyPy
│ │ Classifier: Topic :: Internet :: WWW/HTTP
│ │ Classifier: Topic :: Software Development :: Libraries
│ │ Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4
│ │ Provides-Extra: socks
│ │ Provides-Extra: secure
│ │ +Provides-Extra: brotli
│ --- urllib3-1.24.1/test/test_no_ssl.py
├── +++ urllib3-1.25.3/test/test_no_ssl.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/appengine/conftest.py
├── +++ urllib3-1.25.3/test/appengine/conftest.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/server.csr
├── +++ urllib3-1.25.3/dummyserver/certs/server.csr
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/with_dummyserver/test_proxy_poolmanager.py
├── +++ urllib3-1.25.3/test/with_dummyserver/test_proxy_poolmanager.py
│┄ Files similar despite different names (difference score: 19)
│ │ @@ -24,15 +24,15 @@
│ │ self.http_port)
│ │ self.https_url = 'https://%s:%d' % (self.https_host, self.https_port)
│ │ self.https_url_alt = 'https://%s:%d' % (self.https_host_alt,
│ │ self.https_port)
│ │ self.proxy_url = 'http://%s:%d' % (self.proxy_host, self.proxy_port)
│ │
│ │ def test_basic_proxy(self):
│ │ - http = proxy_from_url(self.proxy_url)
│ │ + http = proxy_from_url(self.proxy_url, ca_certs=DEFAULT_CA)
│ │ self.addCleanup(http.clear)
│ │
│ │ r = http.request('GET', '%s/' % self.http_url)
│ │ self.assertEqual(r.status, 200)
│ │
│ │ r = http.request('GET', '%s/' % self.https_url)
│ │ self.assertEqual(r.status, 200)
│ │ @@ -62,15 +62,15 @@
│ │ try:
│ │ http.request('GET', '%s/' % self.http_url)
│ │ self.fail("Failed to raise retry error.")
│ │ except MaxRetryError as e:
│ │ self.assertEqual(type(e.reason), ProxyError)
│ │
│ │ def test_oldapi(self):
│ │ - http = ProxyManager(connection_from_url(self.proxy_url))
│ │ + http = ProxyManager(connection_from_url(self.proxy_url), ca_certs=DEFAULT_CA)
│ │ self.addCleanup(http.clear)
│ │
│ │ r = http.request('GET', '%s/' % self.http_url)
│ │ self.assertEqual(r.status, 200)
│ │
│ │ r = http.request('GET', '%s/' % self.https_url)
│ │ self.assertEqual(r.status, 200)
│ │ @@ -142,15 +142,15 @@
│ │
│ │ r = http.request('GET', '%s/redirect' % self.http_url,
│ │ fields={'target': '%s/echo?a=b' % self.http_url_alt},
│ │ timeout=1, retries=1)
│ │ self.assertNotEqual(r._pool.host, self.http_host_alt)
│ │
│ │ def test_cross_protocol_redirect(self):
│ │ - http = proxy_from_url(self.proxy_url)
│ │ + http = proxy_from_url(self.proxy_url, ca_certs=DEFAULT_CA)
│ │ self.addCleanup(http.clear)
│ │
│ │ cross_protocol_location = '%s/echo?a=b' % self.https_url
│ │ try:
│ │ http.request('GET', '%s/redirect' % self.http_url,
│ │ fields={'target': cross_protocol_location},
│ │ timeout=1, retries=0)
│ │ @@ -162,15 +162,16 @@
│ │ r = http.request('GET', '%s/redirect' % self.http_url,
│ │ fields={'target': '%s/echo?a=b' % self.https_url},
│ │ timeout=1, retries=1)
│ │ self.assertEqual(r._pool.host, self.https_host)
│ │
│ │ def test_headers(self):
│ │ http = proxy_from_url(self.proxy_url, headers={'Foo': 'bar'},
│ │ - proxy_headers={'Hickory': 'dickory'})
│ │ + proxy_headers={'Hickory': 'dickory'},
│ │ + ca_certs=DEFAULT_CA)
│ │ self.addCleanup(http.clear)
│ │
│ │ r = http.request_encode_url('GET', '%s/headers' % self.http_url)
│ │ returned_headers = json.loads(r.data.decode())
│ │ self.assertEqual(returned_headers.get('Foo'), 'bar')
│ │ self.assertEqual(returned_headers.get('Hickory'), 'dickory')
│ │ self.assertEqual(returned_headers.get('Host'),
│ │ @@ -186,21 +187,14 @@
│ │ r = http.request_encode_url('GET', '%s/headers' % self.https_url)
│ │ returned_headers = json.loads(r.data.decode())
│ │ self.assertEqual(returned_headers.get('Foo'), 'bar')
│ │ self.assertIsNone(returned_headers.get('Hickory'))
│ │ self.assertEqual(returned_headers.get('Host'),
│ │ '%s:%s' % (self.https_host, self.https_port))
│ │
│ │ - r = http.request_encode_url('GET', '%s/headers' % self.https_url_alt)
│ │ - returned_headers = json.loads(r.data.decode())
│ │ - self.assertEqual(returned_headers.get('Foo'), 'bar')
│ │ - self.assertIsNone(returned_headers.get('Hickory'))
│ │ - self.assertEqual(returned_headers.get('Host'),
│ │ - '%s:%s' % (self.https_host_alt, self.https_port))
│ │ -
│ │ r = http.request_encode_body('POST', '%s/headers' % self.http_url)
│ │ returned_headers = json.loads(r.data.decode())
│ │ self.assertEqual(returned_headers.get('Foo'), 'bar')
│ │ self.assertEqual(returned_headers.get('Hickory'), 'dickory')
│ │ self.assertEqual(returned_headers.get('Host'),
│ │ '%s:%s' % (self.http_host, self.http_port))
│ │
│ │ @@ -250,15 +244,15 @@
│ │ request_headers = HTTPHeaderDict(baz='quux')
│ │ r = http.request('GET', '%s/headers' % self.http_url, headers=request_headers)
│ │ returned_headers = json.loads(r.data.decode())
│ │ self.assertEqual(returned_headers.get('Foo'), 'bar')
│ │ self.assertEqual(returned_headers.get('Baz'), 'quux')
│ │
│ │ def test_proxy_pooling(self):
│ │ - http = proxy_from_url(self.proxy_url)
│ │ + http = proxy_from_url(self.proxy_url, cert_reqs='NONE')
│ │ self.addCleanup(http.clear)
│ │
│ │ for x in range(2):
│ │ http.urlopen('GET', self.http_url)
│ │ self.assertEqual(len(http.pools), 1)
│ │
│ │ for x in range(2):
│ │ @@ -316,15 +310,15 @@
│ │ https.request('GET', self.http_url)
│ │ self.fail("Failed to raise retry error.")
│ │ except MaxRetryError as e:
│ │ self.assertEqual(type(e.reason), ConnectTimeoutError)
│ │
│ │ def test_scheme_host_case_insensitive(self):
│ │ """Assert that upper-case schemes and hosts are normalized."""
│ │ - http = proxy_from_url(self.proxy_url.upper())
│ │ + http = proxy_from_url(self.proxy_url.upper(), ca_certs=DEFAULT_CA)
│ │ self.addCleanup(http.clear)
│ │
│ │ r = http.request('GET', '%s/' % self.http_url.upper())
│ │ self.assertEqual(r.status, 200)
│ │
│ │ r = http.request('GET', '%s/' % self.https_url.upper())
│ │ self.assertEqual(r.status, 200)
│ │ @@ -338,15 +332,15 @@
│ │ self.http_port)
│ │ self.https_url = 'https://%s:%d' % (self.https_host, self.https_port)
│ │ self.https_url_alt = 'https://%s:%d' % (self.https_host_alt,
│ │ self.https_port)
│ │ self.proxy_url = 'http://[%s]:%d' % (self.proxy_host, self.proxy_port)
│ │
│ │ def test_basic_ipv6_proxy(self):
│ │ - http = proxy_from_url(self.proxy_url)
│ │ + http = proxy_from_url(self.proxy_url, ca_certs=DEFAULT_CA)
│ │ self.addCleanup(http.clear)
│ │
│ │ r = http.request('GET', '%s/' % self.http_url)
│ │ self.assertEqual(r.status, 200)
│ │
│ │ r = http.request('GET', '%s/' % self.https_url)
│ │ self.assertEqual(r.status, 200)
│ --- urllib3-1.24.1/src/urllib3/contrib/ntlmpool.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/ntlmpool.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/dummyserver/certs/client_intermediate.pem
├── +++ urllib3-1.25.3/dummyserver/certs/client_intermediate.pem
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/contrib/_securetransport/bindings.py
├── +++ urllib3-1.25.3/src/urllib3/contrib/_securetransport/bindings.py
│┄ Files similar despite different names (difference score: 8)
│ │ @@ -512,14 +512,16 @@
│ │ kSSLSessionOptionBreakOnServerAuth = 0
│ │
│ │ kSSLProtocol2 = 1
│ │ kSSLProtocol3 = 2
│ │ kTLSProtocol1 = 4
│ │ kTLSProtocol11 = 7
│ │ kTLSProtocol12 = 8
│ │ + kTLSProtocol13 = 10
│ │ + kTLSProtocolMaxSupported = 999
│ │
│ │ kSSLClientSide = 1
│ │ kSSLStreamType = 0
│ │
│ │ kSecFormatPEMSequence = 10
│ │
│ │ kSecTrustResultInvalid = 0
│ │ @@ -554,40 +556,38 @@
│ │
│ │ errSecVerifyFailed = -67808
│ │ errSecNoTrustSettings = -25263
│ │ errSecItemNotFound = -25300
│ │ errSecInvalidTrustSettings = -25262
│ │
│ │ # Cipher suites. We only pick the ones our default cipher string allows.
│ │ + # Source: https://developer.apple.com/documentation/security/1550981-ssl_cipher_suite_values
│ │ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C
│ │ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030
│ │ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B
│ │ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F
│ │ - TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3
│ │ + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9
│ │ + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8
│ │ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F
│ │ - TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2
│ │ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E
│ │ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024
│ │ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028
│ │ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A
│ │ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014
│ │ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B
│ │ - TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A
│ │ TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039
│ │ - TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038
│ │ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023
│ │ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027
│ │ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009
│ │ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013
│ │ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067
│ │ - TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040
│ │ TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033
│ │ - TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032
│ │ TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D
│ │ TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C
│ │ TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D
│ │ TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C
│ │ TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035
│ │ TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F
│ │ TLS_AES_128_GCM_SHA256 = 0x1301
│ │ TLS_AES_256_GCM_SHA384 = 0x1302
│ │ - TLS_CHACHA20_POLY1305_SHA256 = 0x1303
│ │ + TLS_AES_128_CCM_8_SHA256 = 0x1305
│ │ + TLS_AES_128_CCM_SHA256 = 0x1304
│ --- urllib3-1.24.1/src/urllib3/connection.py
├── +++ urllib3-1.25.3/src/urllib3/connection.py
│┄ Files similar despite different names (difference score: 26)
│ │ @@ -15,18 +15,19 @@
│ │ except (ImportError, AttributeError): # Platform-specific: No SSL.
│ │ ssl = None
│ │
│ │ class BaseSSLError(BaseException):
│ │ pass
│ │
│ │
│ │ -try: # Python 3:
│ │ - # Not a no-op, we're adding this to the namespace so it can be imported.
│ │ +try:
│ │ + # Python 3: not a no-op, we're adding this to the namespace so it can be imported.
│ │ ConnectionError = ConnectionError
│ │ -except NameError: # Python 2:
│ │ +except NameError:
│ │ + # Python 2
│ │ class ConnectionError(Exception):
│ │ pass
│ │
│ │
│ │ from .exceptions import (
│ │ NewConnectionError,
│ │ ConnectTimeoutError,
│ │ @@ -97,15 +98,15 @@
│ │ #: ``[(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]``
│ │ default_socket_options = [(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]
│ │
│ │ #: Whether this connection verifies the host's certificate.
│ │ is_verified = False
│ │
│ │ def __init__(self, *args, **kw):
│ │ - if six.PY3: # Python 3
│ │ + if six.PY3:
│ │ kw.pop('strict', None)
│ │
│ │ # Pre-set source_address.
│ │ self.source_address = kw.get('source_address')
│ │
│ │ #: The socket options provided by the user. If no options are
│ │ #: provided, we use the default options.
│ │ @@ -154,28 +155,29 @@
│ │ if self.socket_options:
│ │ extra_kw['socket_options'] = self.socket_options
│ │
│ │ try:
│ │ conn = connection.create_connection(
│ │ (self._dns_host, self.port), self.timeout, **extra_kw)
│ │
│ │ - except SocketTimeout as e:
│ │ + except SocketTimeout:
│ │ raise ConnectTimeoutError(
│ │ self, "Connection to %s timed out. (connect timeout=%s)" %
│ │ (self.host, self.timeout))
│ │
│ │ except SocketError as e:
│ │ raise NewConnectionError(
│ │ self, "Failed to establish a new connection: %s" % e)
│ │
│ │ return conn
│ │
│ │ def _prepare_conn(self, conn):
│ │ self.sock = conn
│ │ - if self._tunnel_host:
│ │ + # Google App Engine's httplib does not define _tunnel_host
│ │ + if getattr(self, '_tunnel_host', None):
│ │ # TODO: Fix tunnel so it doesn't depend on self.sock state.
│ │ self._tunnel()
│ │ # Mark this connection as not reusable
│ │ self.auto_open = 0
│ │
│ │ def connect(self):
│ │ conn = self._new_conn()
│ │ @@ -222,43 +224,57 @@
│ │
│ │ class HTTPSConnection(HTTPConnection):
│ │ default_port = port_by_scheme['https']
│ │
│ │ ssl_version = None
│ │
│ │ def __init__(self, host, port=None, key_file=None, cert_file=None,
│ │ - strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
│ │ + key_password=None, strict=None,
│ │ + timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
│ │ ssl_context=None, server_hostname=None, **kw):
│ │
│ │ HTTPConnection.__init__(self, host, port, strict=strict,
│ │ timeout=timeout, **kw)
│ │
│ │ self.key_file = key_file
│ │ self.cert_file = cert_file
│ │ + self.key_password = key_password
│ │ self.ssl_context = ssl_context
│ │ self.server_hostname = server_hostname
│ │
│ │ # Required property for Google AppEngine 1.9.0 which otherwise causes
│ │ # HTTPS requests to go out as HTTP. (See Issue #356)
│ │ self._protocol = 'https'
│ │
│ │ def connect(self):
│ │ conn = self._new_conn()
│ │ self._prepare_conn(conn)
│ │
│ │ + # Wrap socket using verification with the root certs in
│ │ + # trusted_root_certs
│ │ + default_ssl_context = False
│ │ if self.ssl_context is None:
│ │ + default_ssl_context = True
│ │ self.ssl_context = create_urllib3_context(
│ │ - ssl_version=resolve_ssl_version(None),
│ │ - cert_reqs=resolve_cert_reqs(None),
│ │ + ssl_version=resolve_ssl_version(self.ssl_version),
│ │ + cert_reqs=resolve_cert_reqs(self.cert_reqs),
│ │ )
│ │
│ │ + # Try to load OS default certs if none are given.
│ │ + # Works well on Windows (requires Python3.4+)
│ │ + context = self.ssl_context
│ │ + if (not self.ca_certs and not self.ca_cert_dir and default_ssl_context
│ │ + and hasattr(context, 'load_default_certs')):
│ │ + context.load_default_certs()
│ │ +
│ │ self.sock = ssl_wrap_socket(
│ │ sock=conn,
│ │ keyfile=self.key_file,
│ │ certfile=self.cert_file,
│ │ + key_password=self.key_password,
│ │ ssl_context=self.ssl_context,
│ │ server_hostname=self.server_hostname
│ │ )
│ │
│ │
│ │ class VerifiedHTTPSConnection(HTTPSConnection):
│ │ """
│ │ @@ -268,44 +284,44 @@
│ │ cert_reqs = None
│ │ ca_certs = None
│ │ ca_cert_dir = None
│ │ ssl_version = None
│ │ assert_fingerprint = None
│ │
│ │ def set_cert(self, key_file=None, cert_file=None,
│ │ - cert_reqs=None, ca_certs=None,
│ │ + cert_reqs=None, key_password=None, ca_certs=None,
│ │ assert_hostname=None, assert_fingerprint=None,
│ │ ca_cert_dir=None):
│ │ """
│ │ This method should only be called once, before the connection is used.
│ │ """
│ │ - # If cert_reqs is not provided, we can try to guess. If the user gave
│ │ - # us a cert database, we assume they want to use it: otherwise, if
│ │ - # they gave us an SSL Context object we should use whatever is set for
│ │ - # it.
│ │ + # If cert_reqs is not provided we'll assume CERT_REQUIRED unless we also
│ │ + # have an SSLContext object in which case we'll use its verify_mode.
│ │ if cert_reqs is None:
│ │ - if ca_certs or ca_cert_dir:
│ │ - cert_reqs = 'CERT_REQUIRED'
│ │ - elif self.ssl_context is not None:
│ │ + if self.ssl_context is not None:
│ │ cert_reqs = self.ssl_context.verify_mode
│ │ + else:
│ │ + cert_reqs = resolve_cert_reqs(None)
│ │
│ │ self.key_file = key_file
│ │ self.cert_file = cert_file
│ │ self.cert_reqs = cert_reqs
│ │ + self.key_password = key_password
│ │ self.assert_hostname = assert_hostname
│ │ self.assert_fingerprint = assert_fingerprint
│ │ self.ca_certs = ca_certs and os.path.expanduser(ca_certs)
│ │ self.ca_cert_dir = ca_cert_dir and os.path.expanduser(ca_cert_dir)
│ │
│ │ def connect(self):
│ │ # Add certificate verification
│ │ conn = self._new_conn()
│ │ hostname = self.host
│ │
│ │ - if self._tunnel_host:
│ │ + # Google App Engine's httplib does not define _tunnel_host
│ │ + if getattr(self, '_tunnel_host', None):
│ │ self.sock = conn
│ │ # Calls self._set_hostport(), so self.host is
│ │ # self._tunnel_host below.
│ │ self._tunnel()
│ │ # Mark this connection as not reusable
│ │ self.auto_open = 0
│ │
│ │ @@ -322,26 +338,36 @@
│ │ 'System time is way off (before {0}). This will probably '
│ │ 'lead to SSL verification errors').format(RECENT_DATE),
│ │ SystemTimeWarning
│ │ )
│ │
│ │ # Wrap socket using verification with the root certs in
│ │ # trusted_root_certs
│ │ + default_ssl_context = False
│ │ if self.ssl_context is None:
│ │ + default_ssl_context = True
│ │ self.ssl_context = create_urllib3_context(
│ │ ssl_version=resolve_ssl_version(self.ssl_version),
│ │ cert_reqs=resolve_cert_reqs(self.cert_reqs),
│ │ )
│ │
│ │ context = self.ssl_context
│ │ context.verify_mode = resolve_cert_reqs(self.cert_reqs)
│ │ +
│ │ + # Try to load OS default certs if none are given.
│ │ + # Works well on Windows (requires Python3.4+)
│ │ + if (not self.ca_certs and not self.ca_cert_dir and default_ssl_context
│ │ + and hasattr(context, 'load_default_certs')):
│ │ + context.load_default_certs()
│ │ +
│ │ self.sock = ssl_wrap_socket(
│ │ sock=conn,
│ │ keyfile=self.key_file,
│ │ certfile=self.cert_file,
│ │ + key_password=self.key_password,
│ │ ca_certs=self.ca_certs,
│ │ ca_cert_dir=self.ca_cert_dir,
│ │ server_hostname=server_hostname,
│ │ ssl_context=context)
│ │
│ │ if self.assert_fingerprint:
│ │ assert_fingerprint(self.sock.getpeercert(binary_form=True),
│ --- urllib3-1.24.1/dummyserver/certs/server.no_san.csr
├── +++ urllib3-1.25.3/dummyserver/certs/server.no_san.csr
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/Makefile
├── +++ urllib3-1.25.3/Makefile
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/appengine/test_urlfetch.py
├── +++ urllib3-1.25.3/test/appengine/test_urlfetch.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/CONTRIBUTORS.txt
├── +++ urllib3-1.25.3/CONTRIBUTORS.txt
│┄ Files similar despite different names (difference score: 13)
│ │ @@ -189,15 +189,15 @@
│ │
│ │ * Ville Skyttä <[email protected]>
│ │ * Logging efficiency improvements, spelling fixes, Travis config.
│ │
│ │ * Shige Takeda <[email protected]>
│ │ * Started Recipes documentation and added a recipe about handling concatenated gzip data in HTTP response
│ │
│ │ -* Jesse Shapiro <[email protected]>
│ │ +* Jess Shapiro <[email protected]>
│ │ * Various character-encoding fixes/tweaks
│ │ * Disabling IPv6 DNS when IPv6 connections not supported
│ │
│ │ * David Foster <http://dafoster.net/>
│ │ * Ensure order of request and response headers are preserved.
│ │
│ │ * Jeremy Cline <[email protected]>
│ │ @@ -240,16 +240,16 @@
│ │ * Mike Miller <[email protected]>
│ │ * Logging improvements to include the HTTP(S) port when opening a new connection
│ │
│ │ * Ioannis Tziakos <[email protected]>
│ │ * Fix ``util.selectors._fileobj_to_fd`` to accept ``long``.
│ │ * Update appveyor tox setup to use the 64bit python.
│ │
│ │ -* Akamai (through Jesse Shapiro) <[email protected]>
│ │ - * Ongoing maintenance
│ │ +* Akamai (through Jess Shapiro) <[email protected]>
│ │ + * Ongoing maintenance; 2017-2018
│ │
│ │ * Dominique Leuenberger <[email protected]>
│ │ * Minor fixes in the test suite
│ │
│ │ * Will Bond <[email protected]>
│ │ * Add Python 2.6 support to ``contrib.securetransport``
│ │
│ │ @@ -268,9 +268,12 @@
│ │
│ │ * Tim Bell <https://github.com/timb07>
│ │ * Bugfix for responses with Content-Type: message/* logging warnings
│ │
│ │ * Justin Bramley <https://github.com/jbramleycl>
│ │ * Add ability to handle multiple Content-Encodings
│ │
│ │ +* Katsuhiko YOSHIDA <https://github.com/kyoshidajp>
│ │ + * Remove Authorization header regardless of case when redirecting to cross-site
│ │ +
│ │ * [Your name or handle] <[email or website]>
│ │ * [Brief summary of your changes]
│ --- urllib3-1.24.1/dummyserver/certs/cacert.no_san.pem
├── +++ urllib3-1.25.3/dummyserver/certs/cacert.no_san.pem
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/filepost.py
├── +++ urllib3-1.25.3/src/urllib3/filepost.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/util/response.py
├── +++ urllib3-1.25.3/src/urllib3/util/response.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/with_dummyserver/test_chunked_transfer.py
├── +++ urllib3-1.25.3/test/with_dummyserver/test_chunked_transfer.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/src/urllib3/request.py
├── +++ urllib3-1.25.3/src/urllib3/request.py
│┄ Files similar despite different names (difference score: 0)
│ --- urllib3-1.24.1/test/contrib/test_pyopenssl_dependencies.py
├── +++ urllib3-1.25.3/test/contrib/test_pyopenssl_dependencies.py
│┄ Files similar despite different names (difference score: 33)
│ │ @@ -11,19 +11,28 @@
│ │ )
│ │ except ImportError:
│ │ pass
│ │
│ │
│ │ def setup_module():
│ │ try:
│ │ - from urllib3.contrib.pyopenssl import inject_into_urllib3 # noqa: F401
│ │ + from urllib3.contrib.pyopenssl import inject_into_urllib3
│ │ + inject_into_urllib3()
│ │ except ImportError as e:
│ │ pytest.skip('Could not import PyOpenSSL: %r' % e)
│ │
│ │
│ │ +def teardown_module():
│ │ + try:
│ │ + from urllib3.contrib.pyopenssl import extract_from_urllib3
│ │ + extract_from_urllib3()
│ │ + except ImportError:
│ │ + pass
│ │ +
│ │ +
│ │ class TestPyOpenSSLInjection(unittest.TestCase):
│ │ """
│ │ Tests for error handling in pyopenssl's 'inject_into urllib3'
│ │ """
│ │ def test_inject_validate_fail_cryptography(self):
│ │ """
│ │ Injection should not be supported if cryptography is too old.
│ --- urllib3-1.24.1/dummyserver/certs/cacert.pem
├── +++ urllib3-1.25.3/dummyserver/certs/cacert.pem
│┄ Files similar despite different names (difference score: 0)