mirror of
				https://github.com/django/django.git
				synced 2025-10-30 17:16:10 +00:00 
			
		
		
		
	Fixed #14928 -- Ensure that a fully qualified domain name can be used for runserver. Thanks to Karmel Allison for the report, Łukasz Rekucki for the patch, and claudep for the tests.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@15215 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -9,7 +9,12 @@ from django.core.handlers.wsgi import WSGIHandler | ||||
| from django.core.servers.basehttp import AdminMediaHandler, run, WSGIServerException | ||||
| from django.utils import autoreload | ||||
|  | ||||
| naiveip_re = r'^(?:(?P<addr>\d{1,3}(?:\.\d{1,3}){3}|\[[a-fA-F0-9:]+\]):)?(?P<port>\d+)$' | ||||
| naiveip_re = re.compile(r"""^(?: | ||||
| (?P<addr> | ||||
|     (?P<ipv4>\d{1,3}(?:\.\d{1,3}){3}) |         # IPv4 address | ||||
|     (?P<ipv6>\[[a-fA-F0-9:]+\]) |               # IPv6 address | ||||
|     (?P<fqdn>[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*) # FQDN | ||||
| ):)?(?P<port>\d+)$""", re.X) | ||||
| DEFAULT_PORT = "8000" | ||||
|  | ||||
| class BaseRunserverCommand(BaseCommand): | ||||
| @@ -33,28 +38,29 @@ class BaseRunserverCommand(BaseCommand): | ||||
|  | ||||
|     def handle(self, addrport='', *args, **options): | ||||
|         self.use_ipv6 = options.get('use_ipv6') | ||||
|         if self.use_ipv6 and not hasattr(socket, 'AF_INET6'): | ||||
|         if self.use_ipv6 and not socket.has_ipv6: | ||||
|             raise CommandError('Your Python does not support IPv6.') | ||||
|         if args: | ||||
|             raise CommandError('Usage is runserver %s' % self.args) | ||||
|         self._raw_ipv6 = False | ||||
|         if not addrport: | ||||
|             self.addr = '' | ||||
|             self.port = DEFAULT_PORT | ||||
|         else: | ||||
|             m = re.match(naiveip_re, addrport) | ||||
|             if m is None: | ||||
|                 raise CommandError('%r is not a valid port number' | ||||
|                 raise CommandError('"%s" is not a valid port number ' | ||||
|                                    'or address:port pair.' % addrport) | ||||
|             self.addr, self.port = m.groups() | ||||
|             self.addr, _ipv4, _ipv6, _fqdn, self.port = m.groups() | ||||
|             if not self.port.isdigit(): | ||||
|                 raise CommandError("%r is not a valid port number." % self.port) | ||||
|             if self.addr: | ||||
|                 if self.addr.startswith('[') and self.addr.endswith(']'): | ||||
|                 if _ipv6: | ||||
|                     self.addr = self.addr[1:-1] | ||||
|                     self.use_ipv6 = True | ||||
|                 elif self.use_ipv6: | ||||
|                     raise CommandError('IPv6 addresses must be surrounded ' | ||||
|                                        'with brackets, e.g. [::1].') | ||||
|                     self._raw_ipv6 = True | ||||
|                 elif self.use_ipv6 and not _fqdn: | ||||
|                     raise CommandError('"%s" is not a valid IPv6 address.' % self.addr) | ||||
|         if not self.addr: | ||||
|             self.addr = self.use_ipv6 and '::1' or '127.0.0.1' | ||||
|         self.run(*args, **options) | ||||
| @@ -86,7 +92,7 @@ class BaseRunserverCommand(BaseCommand): | ||||
|         ) % { | ||||
|             "version": self.get_version(), | ||||
|             "settings": settings.SETTINGS_MODULE, | ||||
|             "addr": self.use_ipv6 and '[%s]' % self.addr or self.addr, | ||||
|             "addr": self._raw_ipv6 and '[%s]' % self.addr or self.addr, | ||||
|             "port": self.port, | ||||
|             "quit_command": quit_command, | ||||
|         }) | ||||
|   | ||||
| @@ -616,7 +616,7 @@ Example usage:: | ||||
|  | ||||
| Run a FastCGI server as a daemon and write the spawned PID in a file. | ||||
|  | ||||
| runserver [port or ipaddr:port] | ||||
| runserver [port or address:port] | ||||
| ------------------------------- | ||||
|  | ||||
| .. django-admin:: runserver | ||||
| @@ -653,8 +653,10 @@ machines on the network, use its own IP address (e.g. ``192.168.2.1``) or | ||||
|  | ||||
| .. versionchanged:: 1.3 | ||||
|  | ||||
| You can also provide an IPv6 address surrounded by brackets | ||||
| (eg. ``[200a::1]:8000``). This will automaticaly enable IPv6 support. | ||||
| You can provide an IPv6 address surrounded by brackets | ||||
| (e.g. ``[200a::1]:8000``). This will automatically enable IPv6 support. | ||||
|  | ||||
| A hostname containing ASCII-only characters can also be used. | ||||
|  | ||||
| .. django-admin-option:: --adminmedia | ||||
|  | ||||
| @@ -721,6 +723,14 @@ Port 7000 on IPv6 address ``2001:0db8:1234:5678::9``:: | ||||
|  | ||||
|     django-admin.py runserver [2001:0db8:1234:5678::9]:7000 | ||||
|  | ||||
| Port 8000 on IPv4 address of host ``localhost``:: | ||||
|  | ||||
|     django-admin.py runserver localhost:8000 | ||||
|  | ||||
| Port 8000 on IPv6 address of host ``localhost``:: | ||||
|  | ||||
|     django-admin.py runserver -6 localhost:8000 | ||||
|  | ||||
| Serving static files with the development server | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
|   | ||||
| @@ -999,6 +999,61 @@ class ManageValidate(AdminScriptTestCase): | ||||
|         self.assertNoOutput(err) | ||||
|         self.assertOutput(out, '0 errors found') | ||||
|  | ||||
| class ManageRunserver(AdminScriptTestCase): | ||||
|     def setUp(self): | ||||
|         from django.core.management.commands.runserver import BaseRunserverCommand | ||||
|         def monkey_run(*args, **options): return | ||||
|  | ||||
|         self.cmd = BaseRunserverCommand() | ||||
|         self.cmd.run = monkey_run | ||||
|  | ||||
|     def assertServerSettings(self, addr, port, ipv6=None, raw_ipv6=False): | ||||
|         self.assertEqual(self.cmd.addr, addr) | ||||
|         self.assertEqual(self.cmd.port, port) | ||||
|         self.assertEqual(self.cmd.use_ipv6, ipv6) | ||||
|         self.assertEqual(self.cmd._raw_ipv6, raw_ipv6) | ||||
|  | ||||
|     def test_runserver_addrport(self): | ||||
|         self.cmd.handle() | ||||
|         self.assertServerSettings('127.0.0.1', '8000') | ||||
|  | ||||
|         self.cmd.handle(addrport="1.2.3.4:8000") | ||||
|         self.assertServerSettings('1.2.3.4', '8000') | ||||
|  | ||||
|         self.cmd.handle(addrport="7000") | ||||
|         self.assertServerSettings('127.0.0.1', '7000') | ||||
|  | ||||
|         # IPv6 | ||||
|         self.cmd.handle(addrport="", use_ipv6=True) | ||||
|         self.assertServerSettings('::1', '8000', ipv6=True) | ||||
|  | ||||
|         self.cmd.handle(addrport="7000", use_ipv6=True) | ||||
|         self.assertServerSettings('::1', '7000', ipv6=True) | ||||
|  | ||||
|         self.cmd.handle(addrport="[2001:0db8:1234:5678::9]:7000") | ||||
|         self.assertServerSettings('2001:0db8:1234:5678::9', '7000', ipv6=True, raw_ipv6=True) | ||||
|  | ||||
|         # Hostname | ||||
|         self.cmd.handle(addrport="localhost:8000") | ||||
|         self.assertServerSettings('localhost', '8000') | ||||
|  | ||||
|         self.cmd.handle(addrport="test.domain.local:7000") | ||||
|         self.assertServerSettings('test.domain.local', '7000') | ||||
|  | ||||
|         self.cmd.handle(addrport="test.domain.local:7000", use_ipv6=True) | ||||
|         self.assertServerSettings('test.domain.local', '7000', ipv6=True) | ||||
|  | ||||
|         # Potentially ambiguous | ||||
|  | ||||
|         # Only 4 characters, all of which coudl be in an ipv6 address | ||||
|         self.cmd.handle(addrport="beef:7654") | ||||
|         self.assertServerSettings('beef', '7654') | ||||
|  | ||||
|         # Uses only characters that could be in an ipv6 address | ||||
|         self.cmd.handle(addrport="deadbeef:7654") | ||||
|         self.assertServerSettings('deadbeef', '7654') | ||||
|  | ||||
|  | ||||
| ########################################################################## | ||||
| # COMMAND PROCESSING TESTS | ||||
| # Check that user-space commands are correctly handled - in particular, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user