Repository: urllib3/urllib3

Issue:
AttributeError: 'NoneType' object has no attribute 'groups' on simple PoolManager.request
```
http = urllib3.PoolManager(maxsize=10)

url = "http://someaddress:32400/library/sections?"
token = "NotSharingIsSometimesCaring"
get = http.request(method='GET', url=url, headers={'X-Plex-Token': token})
```

Tried macos Mojave with Py 3.7.4 and in docker with python 3.8 
using urllib3  1.25.6

```
$ python3 test.py
Traceback (most recent call last):
  File "test.py", line 9, in <module>
    get = http.request(method='GET', url=url, headers={'X-Plex-Token': token})
  File "/Users/someusername/Library/Python/3.7/lib/python/site-packages/urllib3/request.py", line 76, in request
    method, url, fields=fields, headers=headers, **urlopen_kw
  File "/Users/someusername/Library/Python/3.7/lib/python/site-packages/urllib3/request.py", line 97, in request_encode_url
    return self.urlopen(method, url, **extra_kw)
  File "/Users/someusername/Library/Python/3.7/lib/python/site-packages/urllib3/poolmanager.py", line 330, in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
  File "/Users/someusername/Library/Python/3.7/lib/python/site-packages/urllib3/connectionpool.py", line 615, in urlopen
    url = six.ensure_str(_encode_target(url))
  File "/Users/someusername/Library/Python/3.7/lib/python/site-packages/urllib3/util/url.py", line 328, in _encode_target
    path, query, fragment = TARGET_RE.match(target).groups()
AttributeError: 'NoneType' object has no attribute 'groups'
```


Discussion:

Resolving patch:
diff --git a/dummyserver/handlers.py b/dummyserver/handlers.py
--- a/dummyserver/handlers.py
+++ b/dummyserver/handlers.py
@@ -229,6 +229,10 @@ def echo(self, request):
 
         return Response(request.body)
 
+    def echo_uri(self, request):
+        "Echo back the requested URI"
+        return Response(request.uri)
+
     def encodingrequest(self, request):
         "Check for UA accepting gzip/deflate encoding"
         data = b"hello, world!"
diff --git a/src/urllib3/util/url.py b/src/urllib3/util/url.py
--- a/src/urllib3/util/url.py
+++ b/src/urllib3/util/url.py
@@ -55,7 +55,7 @@
 ZONE_ID_PAT = "(?:%25|%)(?:[" + UNRESERVED_PAT + "]|%[a-fA-F0-9]{2})+"
 IPV6_ADDRZ_PAT = r"\[" + IPV6_PAT + r"(?:" + ZONE_ID_PAT + r")?\]"
 REG_NAME_PAT = r"(?:[^\[\]%:/?#]|%[a-fA-F0-9]{2})*"
-TARGET_RE = re.compile(r"^(/[^?]*)(?:\?([^#]+))?(?:#(.*))?$")
+TARGET_RE = re.compile(r"^(/[^?#]*)(?:\?([^#]*))?(?:#.*)?$")
 
 IPV4_RE = re.compile("^" + IPV4_PAT + "$")
 IPV6_RE = re.compile("^" + IPV6_PAT + "$")
@@ -325,14 +325,11 @@ def _encode_target(target):
     if not target.startswith("/"):
         return target
 
-    path, query, fragment = TARGET_RE.match(target).groups()
+    path, query = TARGET_RE.match(target).groups()
     target = _encode_invalid_chars(path, PATH_CHARS)
     query = _encode_invalid_chars(query, QUERY_CHARS)
-    fragment = _encode_invalid_chars(fragment, FRAGMENT_CHARS)
     if query is not None:
         target += "?" + query
-    if fragment is not None:
-        target += "#" + target
     return target
 
 


Test patch:
diff --git a/test/with_dummyserver/test_poolmanager.py b/test/with_dummyserver/test_poolmanager.py
--- a/test/with_dummyserver/test_poolmanager.py
+++ b/test/with_dummyserver/test_poolmanager.py
@@ -333,6 +333,25 @@ def test_http_with_ca_cert_dir(self):
             r = http.request("GET", "http://%s:%s/" % (self.host, self.port))
             assert r.status == 200
 
+    @pytest.mark.parametrize(
+        ["target", "expected_target"],
+        [
+            ("/echo_uri?q=1#fragment", b"/echo_uri?q=1"),
+            ("/echo_uri?#", b"/echo_uri?"),
+            ("/echo_uri#?", b"/echo_uri"),
+            ("/echo_uri#?#", b"/echo_uri"),
+            ("/echo_uri??#", b"/echo_uri??"),
+            ("/echo_uri?%3f#", b"/echo_uri?%3F"),
+            ("/echo_uri?%3F#", b"/echo_uri?%3F"),
+            ("/echo_uri?[]", b"/echo_uri?%5B%5D"),
+        ],
+    )
+    def test_encode_http_target(self, target, expected_target):
+        with PoolManager() as http:
+            url = "http://%s:%d%s" % (self.host, self.port, target)
+            r = http.request("GET", url)
+            assert r.data == expected_target
+
 
 @pytest.mark.skipif(not HAS_IPV6, reason="IPv6 is not supported on this system")
 class TestIPv6PoolManager(IPv6HTTPDummyServerTestCase):