Skip to content

Commit

Permalink
Validate the scheme in a separate method of URLValidator
Browse files Browse the repository at this point in the history
This allows subclassing URLValidator to do fancier types of validation
such as regex matching, etc.

Refs. #26424
  • Loading branch information
jleclanche committed Jun 9, 2018
1 parent 7a266e2 commit ba7ff46
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 1 deletion.
5 changes: 4 additions & 1 deletion django/core/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def __init__(self, schemes=None, **kwargs):
def __call__(self, value):
# Check first if the scheme is valid
scheme = value.split('://')[0].lower()
if scheme not in self.schemes:
if not self.validate_scheme(scheme):
raise ValidationError(self.message, code=self.code)

# Then check full URL
Expand Down Expand Up @@ -148,6 +148,9 @@ def __call__(self, value):
if len(urlsplit(value).netloc) > 253:
raise ValidationError(self.message, code=self.code)

def validate_scheme(self, scheme):
return scheme in self.schemes


integer_validator = RegexValidator(
_lazy_re_compile(r'^-?\d+\Z'),
Expand Down
28 changes: 28 additions & 0 deletions tests/validators/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,34 @@ def test_func(self):
# Dynamically assemble a test class with the contents of TEST_DATA


class TestURLValidator(SimpleTestCase):
def test_validate_scheme(self):
v = URLValidator(schemes=["http", "https"])
self.assertTrue(v.validate_scheme("http"))
self.assertTrue(v.validate_scheme("https"))
self.assertFalse(v.validate_scheme("ftp"))

def test_validate_scheme_override_false(self):
class CustomURLValidator(URLValidator):
def validate_scheme(self, scheme):
return False

v = CustomURLValidator(schemes=["http"])
for scheme in ["http", "https", "ftp"]:
with self.assertRaises(ValidationError):
v("%s://example.com" % (scheme))

def test_validate_scheme_override_true(self):
class CustomURLValidator(URLValidator):
def validate_scheme(self, scheme):
return True

v = CustomURLValidator(schemes=["http"])
self.assertTrue(v("http://example.com"))
self.assertTrue(v("https://example.com"))
self.assertTrue(v("ftp://example.com"))


class TestSimpleValidators(SimpleTestCase):
def test_single_message(self):
v = ValidationError('Not Valid')
Expand Down

0 comments on commit ba7ff46

Please sign in to comment.