We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
PoolManagers are overly case-sensitive.
In a URI, both scheme and authority are case-insensitive: that is, the scheme, host, and port should all be considered case insensitively (and basically treated as lower-case).

Unfortunately, the PoolManager and ProxyManager do not consistently do that. The biggest problem is in the ProxyManager, where `connection_from_host` will incorrectly treat any HTTPS scheme with a capital letter in it like a HTTP connection (which isn't great), but the flaw is pretty common elsewhere in those objects (e.g. an uppercased host will get a different connection pool to a lowercased host).

At the very minimum we should be using a lowercased scheme at all points in the urllib3 stack. We should also consider whether we want to be case-sensitive about domains (I'm inclined to say that we do not).

Related: kennethreitz/requests#3075.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `urllib3/util/url.py`
Content:
```
1 from __future__ import absolute_import
2 from collections import namedtuple
3 
4 from ..exceptions import LocationParseError
5 
6 
7 url_attrs = ['scheme', 'auth', 'host', 'port', 'path', 'query', 'fragment']
8 
9 
10 class Url(namedtuple('Url', url_attrs)):
11     """
12     Datastructure for representing an HTTP URL. Used as a return value for
13     :func:`parse_url`.
14     """
15     slots = ()
16 
17     def __new__(cls, scheme=None, auth=None, host=None, port=None, path=None,
18                 query=None, fragment=None):
19         if path and not path.startswith('/'):
20             path = '/' + path
21         return super(Url, cls).__new__(cls, scheme, auth, host, port, path,
22                                        query, fragment)
23 
24     @property
25     def hostname(self):
26         """For backwards-compatibility with urlparse. We're nice like that."""
27         return self.host
28 
29     @property
30     def request_uri(self):
31         """Absolute path including the query string."""
32         uri = self.path or '/'
33 
34         if self.query is not None:
35             uri += '?' + self.query
36 
37         return uri
38 
39     @property
40     def netloc(self):
41         """Network location including host and port"""
42         if self.port:
43             return '%s:%d' % (self.host, self.port)
44         return self.host
45 
46     @property
47     def url(self):
48         """
49         Convert self into a url
50 
51         This function should more or less round-trip with :func:`.parse_url`. The
52         returned url may not be exactly the same as the url inputted to
53         :func:`.parse_url`, but it should be equivalent by the RFC (e.g., urls
54         with a blank port will have : removed).
55 
56         Example: ::
57 
58             >>> U = parse_url('http://google.com/mail/')
59             >>> U.url
60             'http://google.com/mail/'
61             >>> Url('http', 'username:password', 'host.com', 80,
62             ... '/path', 'query', 'fragment').url
63             'http://username:password@host.com:80/path?query#fragment'
64         """
65         scheme, auth, host, port, path, query, fragment = self
66         url = ''
67 
68         # We use "is not None" we want things to happen with empty strings (or 0 port)
69         if scheme is not None:
70             url += scheme + '://'
71         if auth is not None:
72             url += auth + '@'
73         if host is not None:
74             url += host
75         if port is not None:
76             url += ':' + str(port)
77         if path is not None:
78             url += path
79         if query is not None:
80             url += '?' + query
81         if fragment is not None:
82             url += '#' + fragment
83 
84         return url
85 
86     def __str__(self):
87         return self.url
88 
89 
90 def split_first(s, delims):
91     """
92     Given a string and an iterable of delimiters, split on the first found
93     delimiter. Return two split parts and the matched delimiter.
94 
95     If not found, then the first part is the full input string.
96 
97     Example::
98 
99         >>> split_first('foo/bar?baz', '?/=')
100         ('foo', 'bar?baz', '/')
101         >>> split_first('foo/bar?baz', '123')
102         ('foo/bar?baz', '', None)
103 
104     Scales linearly with number of delims. Not ideal for large number of delims.
105     """
106     min_idx = None
107     min_delim = None
108     for d in delims:
109         idx = s.find(d)
110         if idx < 0:
111             continue
112 
113         if min_idx is None or idx < min_idx:
114             min_idx = idx
115             min_delim = d
116 
117     if min_idx is None or min_idx < 0:
118         return s, '', None
119 
120     return s[:min_idx], s[min_idx + 1:], min_delim
121 
122 
123 def parse_url(url):
124     """
125     Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is
126     performed to parse incomplete urls. Fields not provided will be None.
127 
128     Partly backwards-compatible with :mod:`urlparse`.
129 
130     Example::
131 
132         >>> parse_url('http://google.com/mail/')
133         Url(scheme='http', host='google.com', port=None, path='/mail/', ...)
134         >>> parse_url('google.com:80')
135         Url(scheme=None, host='google.com', port=80, path=None, ...)
136         >>> parse_url('/foo?bar')
137         Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...)
138     """
139 
140     # While this code has overlap with stdlib's urlparse, it is much
141     # simplified for our needs and less annoying.
142     # Additionally, this implementations does silly things to be optimal
143     # on CPython.
144 
145     if not url:
146         # Empty
147         return Url()
148 
149     scheme = None
150     auth = None
151     host = None
152     port = None
153     path = None
154     fragment = None
155     query = None
156 
157     # Scheme
158     if '://' in url:
159         scheme, url = url.split('://', 1)
160 
161     # Find the earliest Authority Terminator
162     # (http://tools.ietf.org/html/rfc3986#section-3.2)
163     url, path_, delim = split_first(url, ['/', '?', '#'])
164 
165     if delim:
166         # Reassemble the path
167         path = delim + path_
168 
169     # Auth
170     if '@' in url:
171         # Last '@' denotes end of auth part
172         auth, url = url.rsplit('@', 1)
173 
174     # IPv6
175     if url and url[0] == '[':
176         host, url = url.split(']', 1)
177         host += ']'
178 
179     # Port
180     if ':' in url:
181         _host, port = url.split(':', 1)
182 
183         if not host:
184             host = _host
185 
186         if port:
187             # If given, ports must be integers.
188             if not port.isdigit():
189                 raise LocationParseError(url)
190             port = int(port)
191         else:
192             # Blank ports are cool, too. (rfc3986#section-3.2.3)
193             port = None
194 
195     elif not host and url:
196         host = url
197 
198     if not path:
199         return Url(scheme, auth, host, port, path, query, fragment)
200 
201     # Fragment
202     if '#' in path:
203         path, fragment = path.split('#', 1)
204 
205     # Query
206     if '?' in path:
207         path, query = path.split('?', 1)
208 
209     return Url(scheme, auth, host, port, path, query, fragment)
210 
211 
212 def get_host(url):
213     """
214     Deprecated. Use :func:`parse_url` instead.
215     """
216     p = parse_url(url)
217     return p.scheme or 'http', p.hostname, p.port
218
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/urllib3/util/url.py b/urllib3/util/url.py
--- a/urllib3/util/url.py
+++ b/urllib3/util/url.py
@@ -10,7 +10,8 @@
 class Url(namedtuple('Url', url_attrs)):
     """
     Datastructure for representing an HTTP URL. Used as a return value for
-    :func:`parse_url`.
+    :func:`parse_url`. Both the scheme and host are normalized as they are
+    both case-insensitive according to RFC 3986.
     """
     slots = ()
 
@@ -18,6 +19,10 @@
                 query=None, fragment=None):
         if path and not path.startswith('/'):
             path = '/' + path
+        if scheme:
+            scheme = scheme.lower()
+        if host:
+            host = host.lower()
         return super(Url, cls).__new__(cls, scheme, auth, host, port, path,
                                        query, fragment)

{"golden_diff": "diff --git a/urllib3/util/url.py b/urllib3/util/url.py\n--- a/urllib3/util/url.py\n+++ b/urllib3/util/url.py\n@@ -10,7 +10,8 @@\n class Url(namedtuple('Url', url_attrs)):\n     \"\"\"\n     Datastructure for representing an HTTP URL. Used as a return value for\n-    :func:`parse_url`.\n+    :func:`parse_url`. Both the scheme and host are normalized as they are\n+    both case-insensitive according to RFC 3986.\n     \"\"\"\n     slots = ()\n \n@@ -18,6 +19,10 @@\n                 query=None, fragment=None):\n         if path and not path.startswith('/'):\n             path = '/' + path\n+        if scheme:\n+            scheme = scheme.lower()\n+        if host:\n+            host = host.lower()\n         return super(Url, cls).__new__(cls, scheme, auth, host, port, path,\n                                        query, fragment)\n", "issue": "PoolManagers are overly case-sensitive.\nIn a URI, both scheme and authority are case-insensitive: that is, the scheme, host, and port should all be considered case insensitively (and basically treated as lower-case).\n\nUnfortunately, the PoolManager and ProxyManager do not consistently do that. The biggest problem is in the ProxyManager, where `connection_from_host` will incorrectly treat any HTTPS scheme with a capital letter in it like a HTTP connection (which isn't great), but the flaw is pretty common elsewhere in those objects (e.g. an uppercased host will get a different connection pool to a lowercased host).\n\nAt the very minimum we should be using a lowercased scheme at all points in the urllib3 stack. We should also consider whether we want to be case-sensitive about domains (I'm inclined to say that we do not).\n\nRelated: kennethreitz/requests#3075.\n\n", "before_files": [{"content": "from __future__ import absolute_import\nfrom collections import namedtuple\n\nfrom ..exceptions import LocationParseError\n\n\nurl_attrs = ['scheme', 'auth', 'host', 'port', 'path', 'query', 'fragment']\n\n\nclass Url(namedtuple('Url', url_attrs)):\n    \"\"\"\n    Datastructure for representing an HTTP URL. Used as a return value for\n    :func:`parse_url`.\n    \"\"\"\n    slots = ()\n\n    def __new__(cls, scheme=None, auth=None, host=None, port=None, path=None,\n                query=None, fragment=None):\n        if path and not path.startswith('/'):\n            path = '/' + path\n        return super(Url, cls).__new__(cls, scheme, auth, host, port, path,\n                                       query, fragment)\n\n    @property\n    def hostname(self):\n        \"\"\"For backwards-compatibility with urlparse. We're nice like that.\"\"\"\n        return self.host\n\n    @property\n    def request_uri(self):\n        \"\"\"Absolute path including the query string.\"\"\"\n        uri = self.path or '/'\n\n        if self.query is not None:\n            uri += '?' + self.query\n\n        return uri\n\n    @property\n    def netloc(self):\n        \"\"\"Network location including host and port\"\"\"\n        if self.port:\n            return '%s:%d' % (self.host, self.port)\n        return self.host\n\n    @property\n    def url(self):\n        \"\"\"\n        Convert self into a url\n\n        This function should more or less round-trip with :func:`.parse_url`. The\n        returned url may not be exactly the same as the url inputted to\n        :func:`.parse_url`, but it should be equivalent by the RFC (e.g., urls\n        with a blank port will have : removed).\n\n        Example: ::\n\n            >>> U = parse_url('http://google.com/mail/')\n            >>> U.url\n            'http://google.com/mail/'\n            >>> Url('http', 'username:password', 'host.com', 80,\n            ... '/path', 'query', 'fragment').url\n            'http://username:password@host.com:80/path?query#fragment'\n        \"\"\"\n        scheme, auth, host, port, path, query, fragment = self\n        url = ''\n\n        # We use \"is not None\" we want things to happen with empty strings (or 0 port)\n        if scheme is not None:\n            url += scheme + '://'\n        if auth is not None:\n            url += auth + '@'\n        if host is not None:\n            url += host\n        if port is not None:\n            url += ':' + str(port)\n        if path is not None:\n            url += path\n        if query is not None:\n            url += '?' + query\n        if fragment is not None:\n            url += '#' + fragment\n\n        return url\n\n    def __str__(self):\n        return self.url\n\n\ndef split_first(s, delims):\n    \"\"\"\n    Given a string and an iterable of delimiters, split on the first found\n    delimiter. Return two split parts and the matched delimiter.\n\n    If not found, then the first part is the full input string.\n\n    Example::\n\n        >>> split_first('foo/bar?baz', '?/=')\n        ('foo', 'bar?baz', '/')\n        >>> split_first('foo/bar?baz', '123')\n        ('foo/bar?baz', '', None)\n\n    Scales linearly with number of delims. Not ideal for large number of delims.\n    \"\"\"\n    min_idx = None\n    min_delim = None\n    for d in delims:\n        idx = s.find(d)\n        if idx < 0:\n            continue\n\n        if min_idx is None or idx < min_idx:\n            min_idx = idx\n            min_delim = d\n\n    if min_idx is None or min_idx < 0:\n        return s, '', None\n\n    return s[:min_idx], s[min_idx + 1:], min_delim\n\n\ndef parse_url(url):\n    \"\"\"\n    Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is\n    performed to parse incomplete urls. Fields not provided will be None.\n\n    Partly backwards-compatible with :mod:`urlparse`.\n\n    Example::\n\n        >>> parse_url('http://google.com/mail/')\n        Url(scheme='http', host='google.com', port=None, path='/mail/', ...)\n        >>> parse_url('google.com:80')\n        Url(scheme=None, host='google.com', port=80, path=None, ...)\n        >>> parse_url('/foo?bar')\n        Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...)\n    \"\"\"\n\n    # While this code has overlap with stdlib's urlparse, it is much\n    # simplified for our needs and less annoying.\n    # Additionally, this implementations does silly things to be optimal\n    # on CPython.\n\n    if not url:\n        # Empty\n        return Url()\n\n    scheme = None\n    auth = None\n    host = None\n    port = None\n    path = None\n    fragment = None\n    query = None\n\n    # Scheme\n    if '://' in url:\n        scheme, url = url.split('://', 1)\n\n    # Find the earliest Authority Terminator\n    # (http://tools.ietf.org/html/rfc3986#section-3.2)\n    url, path_, delim = split_first(url, ['/', '?', '#'])\n\n    if delim:\n        # Reassemble the path\n        path = delim + path_\n\n    # Auth\n    if '@' in url:\n        # Last '@' denotes end of auth part\n        auth, url = url.rsplit('@', 1)\n\n    # IPv6\n    if url and url[0] == '[':\n        host, url = url.split(']', 1)\n        host += ']'\n\n    # Port\n    if ':' in url:\n        _host, port = url.split(':', 1)\n\n        if not host:\n            host = _host\n\n        if port:\n            # If given, ports must be integers.\n            if not port.isdigit():\n                raise LocationParseError(url)\n            port = int(port)\n        else:\n            # Blank ports are cool, too. (rfc3986#section-3.2.3)\n            port = None\n\n    elif not host and url:\n        host = url\n\n    if not path:\n        return Url(scheme, auth, host, port, path, query, fragment)\n\n    # Fragment\n    if '#' in path:\n        path, fragment = path.split('#', 1)\n\n    # Query\n    if '?' in path:\n        path, query = path.split('?', 1)\n\n    return Url(scheme, auth, host, port, path, query, fragment)\n\n\ndef get_host(url):\n    \"\"\"\n    Deprecated. Use :func:`parse_url` instead.\n    \"\"\"\n    p = parse_url(url)\n    return p.scheme or 'http', p.hostname, p.port\n", "path": "urllib3/util/url.py"}], "after_files": [{"content": "from __future__ import absolute_import\nfrom collections import namedtuple\n\nfrom ..exceptions import LocationParseError\n\n\nurl_attrs = ['scheme', 'auth', 'host', 'port', 'path', 'query', 'fragment']\n\n\nclass Url(namedtuple('Url', url_attrs)):\n    \"\"\"\n    Datastructure for representing an HTTP URL. Used as a return value for\n    :func:`parse_url`. Both the scheme and host are normalized as they are\n    both case-insensitive according to RFC 3986.\n    \"\"\"\n    slots = ()\n\n    def __new__(cls, scheme=None, auth=None, host=None, port=None, path=None,\n                query=None, fragment=None):\n        if path and not path.startswith('/'):\n            path = '/' + path\n        if scheme:\n            scheme = scheme.lower()\n        if host:\n            host = host.lower()\n        return super(Url, cls).__new__(cls, scheme, auth, host, port, path,\n                                       query, fragment)\n\n    @property\n    def hostname(self):\n        \"\"\"For backwards-compatibility with urlparse. We're nice like that.\"\"\"\n        return self.host\n\n    @property\n    def request_uri(self):\n        \"\"\"Absolute path including the query string.\"\"\"\n        uri = self.path or '/'\n\n        if self.query is not None:\n            uri += '?' + self.query\n\n        return uri\n\n    @property\n    def netloc(self):\n        \"\"\"Network location including host and port\"\"\"\n        if self.port:\n            return '%s:%d' % (self.host, self.port)\n        return self.host\n\n    @property\n    def url(self):\n        \"\"\"\n        Convert self into a url\n\n        This function should more or less round-trip with :func:`.parse_url`. The\n        returned url may not be exactly the same as the url inputted to\n        :func:`.parse_url`, but it should be equivalent by the RFC (e.g., urls\n        with a blank port will have : removed).\n\n        Example: ::\n\n            >>> U = parse_url('http://google.com/mail/')\n            >>> U.url\n            'http://google.com/mail/'\n            >>> Url('http', 'username:password', 'host.com', 80,\n            ... '/path', 'query', 'fragment').url\n            'http://username:password@host.com:80/path?query#fragment'\n        \"\"\"\n        scheme, auth, host, port, path, query, fragment = self\n        url = ''\n\n        # We use \"is not None\" we want things to happen with empty strings (or 0 port)\n        if scheme is not None:\n            url += scheme + '://'\n        if auth is not None:\n            url += auth + '@'\n        if host is not None:\n            url += host\n        if port is not None:\n            url += ':' + str(port)\n        if path is not None:\n            url += path\n        if query is not None:\n            url += '?' + query\n        if fragment is not None:\n            url += '#' + fragment\n\n        return url\n\n    def __str__(self):\n        return self.url\n\n\ndef split_first(s, delims):\n    \"\"\"\n    Given a string and an iterable of delimiters, split on the first found\n    delimiter. Return two split parts and the matched delimiter.\n\n    If not found, then the first part is the full input string.\n\n    Example::\n\n        >>> split_first('foo/bar?baz', '?/=')\n        ('foo', 'bar?baz', '/')\n        >>> split_first('foo/bar?baz', '123')\n        ('foo/bar?baz', '', None)\n\n    Scales linearly with number of delims. Not ideal for large number of delims.\n    \"\"\"\n    min_idx = None\n    min_delim = None\n    for d in delims:\n        idx = s.find(d)\n        if idx < 0:\n            continue\n\n        if min_idx is None or idx < min_idx:\n            min_idx = idx\n            min_delim = d\n\n    if min_idx is None or min_idx < 0:\n        return s, '', None\n\n    return s[:min_idx], s[min_idx + 1:], min_delim\n\n\ndef parse_url(url):\n    \"\"\"\n    Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is\n    performed to parse incomplete urls. Fields not provided will be None.\n\n    Partly backwards-compatible with :mod:`urlparse`.\n\n    Example::\n\n        >>> parse_url('http://google.com/mail/')\n        Url(scheme='http', host='google.com', port=None, path='/mail/', ...)\n        >>> parse_url('google.com:80')\n        Url(scheme=None, host='google.com', port=80, path=None, ...)\n        >>> parse_url('/foo?bar')\n        Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...)\n    \"\"\"\n\n    # While this code has overlap with stdlib's urlparse, it is much\n    # simplified for our needs and less annoying.\n    # Additionally, this implementations does silly things to be optimal\n    # on CPython.\n\n    if not url:\n        # Empty\n        return Url()\n\n    scheme = None\n    auth = None\n    host = None\n    port = None\n    path = None\n    fragment = None\n    query = None\n\n    # Scheme\n    if '://' in url:\n        scheme, url = url.split('://', 1)\n\n    # Find the earliest Authority Terminator\n    # (http://tools.ietf.org/html/rfc3986#section-3.2)\n    url, path_, delim = split_first(url, ['/', '?', '#'])\n\n    if delim:\n        # Reassemble the path\n        path = delim + path_\n\n    # Auth\n    if '@' in url:\n        # Last '@' denotes end of auth part\n        auth, url = url.rsplit('@', 1)\n\n    # IPv6\n    if url and url[0] == '[':\n        host, url = url.split(']', 1)\n        host += ']'\n\n    # Port\n    if ':' in url:\n        _host, port = url.split(':', 1)\n\n        if not host:\n            host = _host\n\n        if port:\n            # If given, ports must be integers.\n            if not port.isdigit():\n                raise LocationParseError(url)\n            port = int(port)\n        else:\n            # Blank ports are cool, too. (rfc3986#section-3.2.3)\n            port = None\n\n    elif not host and url:\n        host = url\n\n    if not path:\n        return Url(scheme, auth, host, port, path, query, fragment)\n\n    # Fragment\n    if '#' in path:\n        path, fragment = path.split('#', 1)\n\n    # Query\n    if '?' in path:\n        path, query = path.split('?', 1)\n\n    return Url(scheme, auth, host, port, path, query, fragment)\n\n\ndef get_host(url):\n    \"\"\"\n    Deprecated. Use :func:`parse_url` instead.\n    \"\"\"\n    p = parse_url(url)\n    return p.scheme or 'http', p.hostname, p.port\n", "path": "urllib3/util/url.py"}]}