diff --git a/furl/furl.py b/furl/furl.py index cd6d710..67c275c 100644 --- a/furl/furl.py +++ b/furl/furl.py @@ -223,7 +223,7 @@ def is_valid_encoded_query_value(value): return is_valid_encoded_query_value.regex.match(value) is not None -@static_vars(regex=re.compile(r'[a-zA-Z][a-zA-Z\-\.\+]*')) +@static_vars(regex=re.compile(r'^[a-zA-Z][a-zA-Z0-9\-\.\+]*$')) def is_valid_scheme(scheme): return is_valid_scheme.regex.match(scheme) is not None diff --git a/tests/test_furl.py b/tests/test_furl.py index bc268c8..8c1167c 100644 --- a/tests/test_furl.py +++ b/tests/test_furl.py @@ -1290,6 +1290,17 @@ def test_scheme(self): assert furl.furl('+invalid$scheme://lolsup').scheme is None assert furl.furl('/api/test?url=http://a.com').scheme is None + # A prefix that looks like a scheme isn't one: the scheme regex must be + # anchored at both ends, so a ':' after invalid scheme characters + # doesn't get mis-parsed as a scheme separator. + f = furl.furl('a b:c') + assert f.scheme is None and str(f.path) == 'a%20b:c' + assert furl.furl('foo bar:baz').scheme is None + + # Digits are valid in schemes (RFC 3986) and must still parse. + assert furl.furl('ws2://host').scheme == 'ws2' + assert furl.furl('a1b://host').scheme == 'a1b' + # Empty scheme. f = furl.furl(':') assert f.scheme == '' and f.netloc is None and f.url == ':'