<p dir="auto">Giving the malformed URL <code class="notranslate">http://.com</code> should lead to <code class="notranslate">InvalidURL</code> but results in a misleading <code class="notranslate">UnicodeError</code>.</p>
<h2 dir="auto">Expected Result</h2>
<p dir="auto">Should raise <code class="notranslate">InvalidURL</code>.</p>
<h2 dir="auto">Actual Result</h2>
<p dir="auto">Raises <code class="notranslate">UnicodeError</code>.</p>
<h2 dir="auto">Reproduction Steps</h2>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import requests
requests.get(&quot;https://.com&quot;)"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">requests</span>
<span class="pl-s1">requests</span>.<span class="pl-en">get</span>(<span class="pl-s">"https://.com"</span>)</pre></div>
<p dir="auto">results in:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="---------------------------------------------------------------------------
UnicodeError                              Traceback (most recent call last)
~/miniconda3/lib/python3.7/encodings/idna.py in encode(self, input, errors)
    164                 if not (0 &lt; len(label) &lt; 64):
--&gt; 165                     raise UnicodeError(&quot;label empty or too long&quot;)
    166             if len(labels[-1]) &gt;= 64:

UnicodeError: label empty or too long

The above exception was the direct cause of the following exception:

UnicodeError                              Traceback (most recent call last)
&lt;ipython-input-33-45504cf090ae&gt; in &lt;module&gt;
----&gt; 1 requests.get('http://.com')

~/miniconda3/lib/python3.7/site-packages/requests/api.py in get(url, params, **kwargs)
     73
     74     kwargs.setdefault('allow_redirects', True)
---&gt; 75     return request('get', url, params=params, **kwargs)
     76
     77

~/miniconda3/lib/python3.7/site-packages/requests/api.py in request(method, url, **kwargs)
     58     # cases, and look like a memory leak in others.
     59     with sessions.Session() as session:
---&gt; 60         return session.request(method=method, url=url, **kwargs)
     61
     62

~/miniconda3/lib/python3.7/site-packages/requests/sessions.py in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
    531         }
    532         send_kwargs.update(settings)
--&gt; 533         resp = self.send(prep, **send_kwargs)
    534
    535         return resp

~/miniconda3/lib/python3.7/site-packages/requests/sessions.py in send(self, request, **kwargs)
    644
    645         # Send the request
--&gt; 646         r = adapter.send(request, **kwargs)
    647
    648         # Total elapsed time of the request (approximately)

~/miniconda3/lib/python3.7/site-packages/requests/adapters.py in send(self, request, stream, timeout, verify, cert, proxies)
    447                     decode_content=False,
    448                     retries=self.max_retries,
--&gt; 449                     timeout=timeout
    450                 )
    451

~/miniconda3/lib/python3.7/site-packages/urllib3/connectionpool.py in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)
    598                                                   timeout=timeout_obj,
    599                                                   body=body, headers=headers,
--&gt; 600                                                   chunked=chunked)
    601
    602             # If we're going to release the connection in ``finally:``, then

~/miniconda3/lib/python3.7/site-packages/urllib3/connectionpool.py in _make_request(self, conn, method, url, timeout, chunked, **httplib_request_kw)
    352             conn.request_chunked(method, url, **httplib_request_kw)
    353         else:
--&gt; 354             conn.request(method, url, **httplib_request_kw)
    355
    356         # Reset the timeout for the recv() on the socket

~/miniconda3/lib/python3.7/http/client.py in request(self, method, url, body, headers, encode_chunked)
   1227                 encode_chunked=False):
   1228         &quot;&quot;&quot;Send a complete request to the server.&quot;&quot;&quot;
-&gt; 1229         self._send_request(method, url, body, headers, encode_chunked)
   1230
   1231     def _send_request(self, method, url, body, headers, encode_chunked):

~/miniconda3/lib/python3.7/http/client.py in _send_request(self, method, url, body, headers, encode_chunked)
   1273             # default charset of iso-8859-1.
   1274             body = _encode(body, 'body')
-&gt; 1275         self.endheaders(body, encode_chunked=encode_chunked)
   1276
   1277     def getresponse(self):

~/miniconda3/lib/python3.7/http/client.py in endheaders(self, message_body, encode_chunked)
   1222         else:
   1223             raise CannotSendHeader()
-&gt; 1224         self._send_output(message_body, encode_chunked=encode_chunked)
   1225
   1226     def request(self, method, url, body=None, headers={}, *,

~/miniconda3/lib/python3.7/http/client.py in _send_output(self, message_body, encode_chunked)
   1014         msg = b&quot;\r\n&quot;.join(self._buffer)
   1015         del self._buffer[:]
-&gt; 1016         self.send(msg)
   1017
   1018         if message_body is not None:

~/miniconda3/lib/python3.7/http/client.py in send(self, data)
    954         if self.sock is None:
    955             if self.auto_open:
--&gt; 956                 self.connect()
    957             else:
    958                 raise NotConnected()

~/miniconda3/lib/python3.7/site-packages/urllib3/connection.py in connect(self)
    179
    180     def connect(self):
--&gt; 181         conn = self._new_conn()
    182         self._prepare_conn(conn)
    183

~/miniconda3/lib/python3.7/site-packages/urllib3/connection.py in _new_conn(self)
    157         try:
    158             conn = connection.create_connection(
--&gt; 159                 (self._dns_host, self.port), self.timeout, **extra_kw)
    160
    161         except SocketTimeout:

~/miniconda3/lib/python3.7/site-packages/urllib3/util/connection.py in create_connection(address, timeout, source_address, socket_options)
     55     family = allowed_gai_family()
     56
---&gt; 57     for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
     58         af, socktype, proto, canonname, sa = res
     59         sock = None

~/miniconda3/lib/python3.7/socket.py in getaddrinfo(host, port, family, type, proto, flags)
    746     # and socket type values to enum constants.
    747     addrlist = []
--&gt; 748     for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
    749         af, socktype, proto, canonname, sa = res
    750         addrlist.append((_intenum_converter(af, AddressFamily),

UnicodeError: encoding with 'idna' codec failed (UnicodeError: label empty or too long)"><pre class="notranslate"><code class="notranslate">---------------------------------------------------------------------------
UnicodeError                              Traceback (most recent call last)
~/miniconda3/lib/python3.7/encodings/idna.py in encode(self, input, errors)
    164                 if not (0 &lt; len(label) &lt; 64):
--&gt; 165                     raise UnicodeError("label empty or too long")
    166             if len(labels[-1]) &gt;= 64:

UnicodeError: label empty or too long

The above exception was the direct cause of the following exception:

UnicodeError                              Traceback (most recent call last)
&lt;ipython-input-33-45504cf090ae&gt; in &lt;module&gt;
----&gt; 1 requests.get('http://.com')

~/miniconda3/lib/python3.7/site-packages/requests/api.py in get(url, params, **kwargs)
     73
     74     kwargs.setdefault('allow_redirects', True)
---&gt; 75     return request('get', url, params=params, **kwargs)
     76
     77

~/miniconda3/lib/python3.7/site-packages/requests/api.py in request(method, url, **kwargs)
     58     # cases, and look like a memory leak in others.
     59     with sessions.Session() as session:
---&gt; 60         return session.request(method=method, url=url, **kwargs)
     61
     62

~/miniconda3/lib/python3.7/site-packages/requests/sessions.py in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
    531         }
    532         send_kwargs.update(settings)
--&gt; 533         resp = self.send(prep, **send_kwargs)
    534
    535         return resp

~/miniconda3/lib/python3.7/site-packages/requests/sessions.py in send(self, request, **kwargs)
    644
    645         # Send the request
--&gt; 646         r = adapter.send(request, **kwargs)
    647
    648         # Total elapsed time of the request (approximately)

~/miniconda3/lib/python3.7/site-packages/requests/adapters.py in send(self, request, stream, timeout, verify, cert, proxies)
    447                     decode_content=False,
    448                     retries=self.max_retries,
--&gt; 449                     timeout=timeout
    450                 )
    451

~/miniconda3/lib/python3.7/site-packages/urllib3/connectionpool.py in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)
    598                                                   timeout=timeout_obj,
    599                                                   body=body, headers=headers,
--&gt; 600                                                   chunked=chunked)
    601
    602             # If we're going to release the connection in ``finally:``, then

~/miniconda3/lib/python3.7/site-packages/urllib3/connectionpool.py in _make_request(self, conn, method, url, timeout, chunked, **httplib_request_kw)
    352             conn.request_chunked(method, url, **httplib_request_kw)
    353         else:
--&gt; 354             conn.request(method, url, **httplib_request_kw)
    355
    356         # Reset the timeout for the recv() on the socket

~/miniconda3/lib/python3.7/http/client.py in request(self, method, url, body, headers, encode_chunked)
   1227                 encode_chunked=False):
   1228         """Send a complete request to the server."""
-&gt; 1229         self._send_request(method, url, body, headers, encode_chunked)
   1230
   1231     def _send_request(self, method, url, body, headers, encode_chunked):

~/miniconda3/lib/python3.7/http/client.py in _send_request(self, method, url, body, headers, encode_chunked)
   1273             # default charset of iso-8859-1.
   1274             body = _encode(body, 'body')
-&gt; 1275         self.endheaders(body, encode_chunked=encode_chunked)
   1276
   1277     def getresponse(self):

~/miniconda3/lib/python3.7/http/client.py in endheaders(self, message_body, encode_chunked)
   1222         else:
   1223             raise CannotSendHeader()
-&gt; 1224         self._send_output(message_body, encode_chunked=encode_chunked)
   1225
   1226     def request(self, method, url, body=None, headers={}, *,

~/miniconda3/lib/python3.7/http/client.py in _send_output(self, message_body, encode_chunked)
   1014         msg = b"\r\n".join(self._buffer)
   1015         del self._buffer[:]
-&gt; 1016         self.send(msg)
   1017
   1018         if message_body is not None:

~/miniconda3/lib/python3.7/http/client.py in send(self, data)
    954         if self.sock is None:
    955             if self.auto_open:
--&gt; 956                 self.connect()
    957             else:
    958                 raise NotConnected()

~/miniconda3/lib/python3.7/site-packages/urllib3/connection.py in connect(self)
    179
    180     def connect(self):
--&gt; 181         conn = self._new_conn()
    182         self._prepare_conn(conn)
    183

~/miniconda3/lib/python3.7/site-packages/urllib3/connection.py in _new_conn(self)
    157         try:
    158             conn = connection.create_connection(
--&gt; 159                 (self._dns_host, self.port), self.timeout, **extra_kw)
    160
    161         except SocketTimeout:

~/miniconda3/lib/python3.7/site-packages/urllib3/util/connection.py in create_connection(address, timeout, source_address, socket_options)
     55     family = allowed_gai_family()
     56
---&gt; 57     for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
     58         af, socktype, proto, canonname, sa = res
     59         sock = None

~/miniconda3/lib/python3.7/socket.py in getaddrinfo(host, port, family, type, proto, flags)
    746     # and socket type values to enum constants.
    747     addrlist = []
--&gt; 748     for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
    749         af, socktype, proto, canonname, sa = res
    750         addrlist.append((_intenum_converter(af, AddressFamily),

UnicodeError: encoding with 'idna' codec failed (UnicodeError: label empty or too long)
</code></pre></div>
<h2 dir="auto">System Information</h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ python -m requests.help"><pre class="notranslate"><code class="notranslate">$ python -m requests.help
</code></pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="➔ python -m requests.help
{
  &quot;chardet&quot;: {
    &quot;version&quot;: &quot;3.0.4&quot;
  },
  &quot;cryptography&quot;: {
    &quot;version&quot;: &quot;2.7&quot;
  },
  &quot;idna&quot;: {
    &quot;version&quot;: &quot;2.7&quot;
  },
  &quot;implementation&quot;: {
    &quot;name&quot;: &quot;CPython&quot;,
    &quot;version&quot;: &quot;3.7.3&quot;
  },
  &quot;platform&quot;: {
    &quot;release&quot;: &quot;19.4.0&quot;,
    &quot;system&quot;: &quot;Darwin&quot;
  },
  &quot;pyOpenSSL&quot;: {
    &quot;openssl_version&quot;: &quot;1010103f&quot;,
    &quot;version&quot;: &quot;19.0.0&quot;
  },
  &quot;requests&quot;: {
    &quot;version&quot;: &quot;2.20.1&quot;
  },
  &quot;system_ssl&quot;: {
    &quot;version&quot;: &quot;1010103f&quot;
  },
  &quot;urllib3&quot;: {
    &quot;version&quot;: &quot;1.24.3&quot;
  },
  &quot;using_pyopenssl&quot;: true
}"><pre class="notranslate"><code class="notranslate">➔ python -m requests.help
{
  "chardet": {
    "version": "3.0.4"
  },
  "cryptography": {
    "version": "2.7"
  },
  "idna": {
    "version": "2.7"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.7.3"
  },
  "platform": {
    "release": "19.4.0",
    "system": "Darwin"
  },
  "pyOpenSSL": {
    "openssl_version": "1010103f",
    "version": "19.0.0"
  },
  "requests": {
    "version": "2.20.1"
  },
  "system_ssl": {
    "version": "1010103f"
  },
  "urllib3": {
    "version": "1.24.3"
  },
  "using_pyopenssl": true
}
</code></pre></div>
<p dir="auto">Trying to use a Session object to have a common TLS verify option for a bunch of calls in a CI environment for test with self signed certificates.</p>
<p dir="auto">This works all right when no environment variable is set, but once REQUESTS_CA_BUNDLE or the equivalent curl var is set up, it fails.</p>
<p dir="auto">This probably happens due to the logic in <code class="notranslate">merge_environment_settings()</code> and the merge logic for settings.</p>
<h2 dir="auto">Expected Result</h2>
<p dir="auto">Verify works, the explicitly configured ca path on the Session object is used.<br>
&lt;Response [200]&gt;</p>
<h2 dir="auto">Actual Result</h2>
<p dir="auto">Verify fails, the implicitly configured environment setting overrides the explicit setting on the Session.</p>
<p dir="auto">SSLError: HTTPSConnectionPool(host='example.org', port=8443): Max retries exceeded with url: /login (Caused by SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED]</p>
<h2 dir="auto">Reproduction Steps</h2>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import requests, os
# One of the many linux default locations for a ca bundle
os.environ['REQUESTS_CA_BUNDLE'] = '/etc/ssl/certs/ca-bundle.crt'
ca = &quot;/home/schlenk/sqlite/certs/ca.crt&quot;
print requests.get('https://myhost.example.org:8443/', verify=ca)
# This gives a &lt;Response [200]&gt;
# Now try with Session
s = requests.Session()
s.verify = ca
s.get('https://myhost.example.org:8443/')
# This throws an SSLError exception
# SSLError: HTTPSConnectionPool(host='myhost.example.org', port=8443): Max retries exceeded with url:  / (Caused by SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:726)'),))
# But this works just fine
s.get('https://myhost.example.org:8443/', verify=ca)
&lt;Response [200]&gt;"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">requests</span>, <span class="pl-s1">os</span>
<span class="pl-c"># One of the many linux default locations for a ca bundle</span>
<span class="pl-s1">os</span>.<span class="pl-s1">environ</span>[<span class="pl-s">'REQUESTS_CA_BUNDLE'</span>] <span class="pl-c1">=</span> <span class="pl-s">'/etc/ssl/certs/ca-bundle.crt'</span>
<span class="pl-s1">ca</span> <span class="pl-c1">=</span> <span class="pl-s">"/home/schlenk/sqlite/certs/ca.crt"</span>
<span class="pl-k">print</span> <span class="pl-s1">requests</span>.<span class="pl-en">get</span>(<span class="pl-s">'https://myhost.example.org:8443/'</span>, <span class="pl-s1">verify</span><span class="pl-c1">=</span><span class="pl-s1">ca</span>)
<span class="pl-c"># This gives a &lt;Response [200]&gt;</span>
<span class="pl-c"># Now try with Session</span>
<span class="pl-s1">s</span> <span class="pl-c1">=</span> <span class="pl-s1">requests</span>.<span class="pl-v">Session</span>()
<span class="pl-s1">s</span>.<span class="pl-s1">verify</span> <span class="pl-c1">=</span> <span class="pl-s1">ca</span>
<span class="pl-s1">s</span>.<span class="pl-en">get</span>(<span class="pl-s">'https://myhost.example.org:8443/'</span>)
<span class="pl-c"># This throws an SSLError exception</span>
<span class="pl-c"># SSLError: HTTPSConnectionPool(host='myhost.example.org', port=8443): Max retries exceeded with url:  / (Caused by SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:726)'),))</span>
<span class="pl-c"># But this works just fine</span>
<span class="pl-s1">s</span>.<span class="pl-en">get</span>(<span class="pl-s">'https://myhost.example.org:8443/'</span>, <span class="pl-s1">verify</span><span class="pl-c1">=</span><span class="pl-s1">ca</span>)
<span class="pl-c1">&lt;</span><span class="pl-v">Response</span> [<span class="pl-c1">200</span>]<span class="pl-c1">&gt;</span></pre></div>
<h2 dir="auto">System Information</h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ python -m requests.help"><pre class="notranslate"><code class="notranslate">$ python -m requests.help
</code></pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="d:\code\trunk64&gt;win32\debug\img\python.exe -m requests.help
{
  &quot;chardet&quot;: {
    &quot;version&quot;: &quot;3.0.4&quot;
  },
  &quot;cryptography&quot;: {
    &quot;version&quot;: &quot;2.2.2&quot;
  },
  &quot;idna&quot;: {
    &quot;version&quot;: &quot;2.6&quot;
  },
  &quot;implementation&quot;: {
    &quot;name&quot;: &quot;CPython&quot;,
    &quot;version&quot;: &quot;2.7.15&quot;
  },
  &quot;platform&quot;: {
    &quot;release&quot;: &quot;2012ServerR2&quot;,
    &quot;system&quot;: &quot;Windows&quot;
  },
  &quot;pyOpenSSL&quot;: {
    &quot;openssl_version&quot;: &quot;100020df&quot;,
    &quot;version&quot;: &quot;18.0.0&quot;
  },
  &quot;requests&quot;: {
    &quot;version&quot;: &quot;2.18.4&quot;
  },
  &quot;system_ssl&quot;: {
    &quot;version&quot;: &quot;100020ff&quot;
  },
  &quot;urllib3&quot;: {
    &quot;version&quot;: &quot;1.22&quot;
  },
  &quot;using_pyopenssl&quot;: true
}"><pre class="notranslate"><code class="notranslate">d:\code\trunk64&gt;win32\debug\img\python.exe -m requests.help
{
  "chardet": {
    "version": "3.0.4"
  },
  "cryptography": {
    "version": "2.2.2"
  },
  "idna": {
    "version": "2.6"
  },
  "implementation": {
    "name": "CPython",
    "version": "2.7.15"
  },
  "platform": {
    "release": "2012ServerR2",
    "system": "Windows"
  },
  "pyOpenSSL": {
    "openssl_version": "100020df",
    "version": "18.0.0"
  },
  "requests": {
    "version": "2.18.4"
  },
  "system_ssl": {
    "version": "100020ff"
  },
  "urllib3": {
    "version": "1.22"
  },
  "using_pyopenssl": true
}
</code></pre></div>
<p dir="auto">Same issue happens on Linux with identical versions.</p>