1
0
mirror of https://github.com/django/django.git synced 2025-11-07 07:15:35 +00:00

Fixed #7735 -- Added support for IPv6 adresses to runserver and testserver management command. Thanks to Jason Alonso and Łukasz Rekucki for the report and initial patches.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14711 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jannis Leidel
2010-11-26 13:33:53 +00:00
parent 132afbf8ee
commit 6a32e253f6
5 changed files with 82 additions and 27 deletions

View File

@@ -1,14 +1,21 @@
from optparse import make_option
import os
import re
import sys
import socket
from django.core.management.base import BaseCommand, CommandError
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+)$'
DEFAULT_PORT = "8000"
class BaseRunserverCommand(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--ipv6', '-6', action='store_true', dest='use_ipv6', default=False,
help='Tells Django to use a IPv6 address.'),
make_option('--noreload', action='store_false', dest='use_reloader', default=True,
help='Tells Django to NOT use the auto-reloader.'),
)
@@ -25,22 +32,31 @@ class BaseRunserverCommand(BaseCommand):
return WSGIHandler()
def handle(self, addrport='', *args, **options):
self.use_ipv6 = options.get('use_ipv6')
if self.use_ipv6 and not hasattr(socket, 'AF_INET6'):
raise CommandError('Your Python does not support IPv6.')
if args:
raise CommandError('Usage is runserver %s' % self.args)
if not addrport:
self.addr = ''
self.port = '8000'
self.port = DEFAULT_PORT
else:
try:
self.addr, self.port = addrport.split(':')
except ValueError:
self.addr, self.port = '', addrport
m = re.match(naiveip_re, addrport)
if m is None:
raise CommandError('%r is not a valid port number'
'or address:port pair.' % addrport)
self.addr, 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(']'):
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].')
if not self.addr:
self.addr = '127.0.0.1'
if not self.port.isdigit():
raise CommandError("%r is not a valid port number." % self.port)
self.addr = self.use_ipv6 and '::1' or '127.0.0.1'
self.run(*args, **options)
def run(self, *args, **options):
@@ -70,7 +86,7 @@ class BaseRunserverCommand(BaseCommand):
) % {
"version": self.get_version(),
"settings": settings.SETTINGS_MODULE,
"addr": self.addr,
"addr": self.use_ipv6 and '[%s]' % self.addr or self.addr,
"port": self.port,
"quit_command": quit_command,
})
@@ -81,7 +97,7 @@ class BaseRunserverCommand(BaseCommand):
try:
handler = self.get_handler(*args, **options)
run(self.addr, int(self.port), handler)
run(self.addr, int(self.port), handler, ipv6=self.use_ipv6)
except WSGIServerException, e:
# Use helpful error messages instead of ugly tracebacks.
ERRORS = {

View File

@@ -9,6 +9,8 @@ class Command(BaseCommand):
make_option('--addrport', action='store', dest='addrport',
type='string', default='',
help='port number or ipaddr:port to run the server on'),
make_option('--ipv6', '-6', action='store_true', dest='use_ipv6', default=False,
help='Tells Django to use a IPv6 address.'),
)
help = 'Runs a development server with data from the given fixture(s).'
args = '[fixture ...]'
@@ -33,4 +35,4 @@ class Command(BaseCommand):
# a strange error -- it causes this handle() method to be called
# multiple times.
shutdown_message = '\nServer stopped.\nNote that the test database, %r, has not been deleted. You can explore it on your own.' % db_name
call_command('runserver', addrport=addrport, shutdown_message=shutdown_message, use_reloader=False)
call_command('runserver', addrport=addrport, shutdown_message=shutdown_message, use_reloader=False, use_ipv6=options['use_ipv6'])

View File

@@ -10,6 +10,7 @@ been reviewed for security issues. Don't use it for production use.
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import os
import re
import socket
import sys
import urllib
import warnings
@@ -526,6 +527,11 @@ class WSGIServer(HTTPServer):
"""BaseHTTPServer that implements the Python WSGI protocol"""
application = None
def __init__(self, *args, **kwargs):
if kwargs.pop('ipv6', False):
self.address_family = socket.AF_INET6
HTTPServer.__init__(self, *args, **kwargs)
def server_bind(self):
"""Override server_bind to store the server name."""
try:
@@ -683,9 +689,8 @@ class AdminMediaHandler(handlers.StaticFilesHandler):
"""
return path.startswith(self.base_url[2]) and not self.base_url[1]
def run(addr, port, wsgi_handler):
def run(addr, port, wsgi_handler, ipv6=False):
server_address = (addr, port)
httpd = WSGIServer(server_address, WSGIRequestHandler)
httpd = WSGIServer(server_address, WSGIRequestHandler, ipv6=ipv6)
httpd.set_app(wsgi_handler)
httpd.serve_forever()