commit a2f2e6e47bd4f66af1c91ff327dab61d7a20bdc4
Author: Claude Paroz <claude@2xlibre.net>
Date: Wed Dec 29 15:15:57 2010 +0100
Use custom urllib2 Request to use HEAD instead of GET request to validate url
diff --git a/django/core/validators.py b/django/core/validators.py
index b1b82db..c8af901 100644
|
a
|
b
|
|
| 1 | 1 | import re |
| | 2 | import urllib2 |
| 2 | 3 | import urlparse |
| 3 | 4 | |
| 4 | 5 | from django.core.exceptions import ValidationError |
| … |
… |
class RegexValidator(object):
|
| 38 | 39 | if not self.regex.search(smart_unicode(value)): |
| 39 | 40 | raise ValidationError(self.message, code=self.code) |
| 40 | 41 | |
| | 42 | class HeadRequest(urllib2.Request): |
| | 43 | def get_method(self): |
| | 44 | return "HEAD" |
| | 45 | |
| 41 | 46 | class URLValidator(RegexValidator): |
| 42 | 47 | regex = re.compile( |
| 43 | 48 | r'^https?://' # http:// or https:// |
| … |
… |
class URLValidator(RegexValidator):
|
| 72 | 77 | url = value |
| 73 | 78 | |
| 74 | 79 | if self.verify_exists: |
| 75 | | import urllib2 |
| 76 | 80 | headers = { |
| 77 | 81 | "Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5", |
| 78 | 82 | "Accept-Language": "en-us,en;q=0.5", |
| … |
… |
class URLValidator(RegexValidator):
|
| 80 | 84 | "Connection": "close", |
| 81 | 85 | "User-Agent": self.user_agent, |
| 82 | 86 | } |
| | 87 | broken_error = ValidationError(_(u'This URL appears to be a broken link.'), code='invalid_link') |
| 83 | 88 | try: |
| 84 | | req = urllib2.Request(url, None, headers) |
| | 89 | req = HeadRequest(url, None, headers) |
| 85 | 90 | u = urllib2.urlopen(req) |
| 86 | 91 | except ValueError: |
| 87 | 92 | raise ValidationError(_(u'Enter a valid URL.'), code='invalid') |
| | 93 | except urllib2.HTTPError, e: |
| | 94 | if e.code in (405, 501): |
| | 95 | # Try a GET request (HEAD refused) |
| | 96 | # See also: http://www.w3.org/Protocols/rfc2616/rfc2616.html |
| | 97 | try: |
| | 98 | req = urllib2.Request(url, None, headers) |
| | 99 | u = urllib2.urlopen(req) |
| | 100 | except: |
| | 101 | raise broken_error |
| | 102 | else: |
| | 103 | raise broken_error |
| 88 | 104 | except: # urllib2.URLError, httplib.InvalidURL, etc. |
| 89 | | raise ValidationError(_(u'This URL appears to be a broken link.'), code='invalid_link') |
| | 105 | raise broken_error |
| 90 | 106 | |
| 91 | 107 | |
| 92 | 108 | def validate_integer(value): |
diff --git a/tests/regressiontests/forms/tests/fields.py b/tests/regressiontests/forms/tests/fields.py
index 576a9c3..65c1172 100644
|
a
|
b
|
class FieldsTests(TestCase):
|
| 561 | 561 | self.assertEqual(u'http://www.google.com/', f.clean('http://www.google.com')) # This will fail if there's no Internet connection |
| 562 | 562 | self.assertRaisesErrorWithMessage(ValidationError, "[u'Enter a valid URL.']", f.clean, 'http://example') |
| 563 | 563 | self.assertRaises(ValidationError, f.clean, 'http://www.broken.djangoproject.com') # bad domain |
| | 564 | self.assertRaises(ValidationError, f.clean, 'http://qa-dev.w3.org/link-testsuite/http.php?code=405') # Method not allowed |
| 564 | 565 | try: |
| 565 | 566 | f.clean('http://www.broken.djangoproject.com') # bad domain |
| 566 | 567 | except ValidationError, e: |