Raise a meaningful error for an unknown scheme
MODIFY
src/urllib3/exceptions.py
src/urllib3/exceptions.py
@@ -153,6 +153,16 @@ class LocationParseError(LocationValueError):
self.location = location
+class URLSchemeUnknown(LocationValueError):
+ "Raised when a URL input has an unsupported scheme."
+
+ def __init__(self, scheme):
+ message = "Not supported URL scheme %s" % scheme
+ super(URLSchemeUnknown, self).__init__(message)
+
+ self.scheme = scheme
+
+
class ResponseError(HTTPError):
"Used as a container for an error reason supplied in a MaxRetryError."
GENERIC_ERROR = "too many error responses"
@@ -253,7 +263,7 @@ class InvalidHeader(HTTPError):
pass
-class ProxySchemeUnknown(AssertionError, ValueError):
+class ProxySchemeUnknown(AssertionError, URLSchemeUnknown):
"ProxyManager does not support the supplied scheme"
# TODO(t-8ch): Stop inheriting from AssertionError in v2.0.

MODIFY
src/urllib3/poolmanager.py
src/urllib3/poolmanager.py
@@ -14,6 +14,7 @@ from .exceptions import (
MaxRetryError,
ProxySchemeUnknown,
ProxySchemeUnsupported,
+ URLSchemeUnknown,
)
from .packages import six
from .packages.six.moves.urllib.parse import urljoin
@@ -255,7 +256,9 @@ class PoolManager(RequestMethods):
value must be a key in ``key_fn_by_scheme`` instance variable.
"""
scheme = request_context["scheme"].lower()
- pool_key_constructor = self.key_fn_by_scheme[scheme]
+ pool_key_constructor = self.key_fn_by_scheme.get(scheme)
+ if not pool_key_constructor:
+ raise URLSchemeUnknown(scheme)
pool_key = pool_key_constructor(request_context)
return self.connection_from_pool_key(pool_key, request_context=request_context)

MODIFY
test/with_dummyserver/test_poolmanager.py
test/with_dummyserver/test_poolmanager.py
@@ -6,7 +6,7 @@ from dummyserver.server import HAS_IPV6
from dummyserver.testcase import HTTPDummyServerTestCase, IPv6HTTPDummyServerTestCase
from urllib3.poolmanager import PoolManager
from urllib3.connectionpool import port_by_scheme
-from urllib3.exceptions import MaxRetryError
+from urllib3.exceptions import MaxRetryError, URLSchemeUnknown
from urllib3.util.retry import Retry
from test import LONG_TIMEOUT
@@ -223,6 +223,29 @@ class TestPoolManager(HTTPDummyServerTestCase):
assert r._pool.num_connections == 1
assert len(http.pools) == 1
+ def test_unknown_scheme(self):
+ with PoolManager() as http:
+ unknown_scheme = "unknown"
+ unknown_scheme_url = "%s://host" % unknown_scheme
+ with pytest.raises(URLSchemeUnknown) as e:
+ r = http.request("GET", unknown_scheme_url)
+ assert e.value.scheme == unknown_scheme
+ r = http.request(
+ "GET",
+ "%s/redirect" % self.base_url,
+ fields={"target": unknown_scheme_url},
+ redirect=False,
+ )
+ assert r.status == 303
+ assert r.headers.get("Location") == unknown_scheme_url
+ with pytest.raises(URLSchemeUnknown) as e:
+ r = http.request(
+ "GET",
+ "%s/redirect" % self.base_url,
+ fields={"target": unknown_scheme_url},
+ )
+ assert e.value.scheme == unknown_scheme
+
def test_raise_on_redirect(self):
with PoolManager() as http:
r = http.request(

Raise a meaningful error for an unknown scheme (#1872)