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: |