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:
@@ -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 = {
|
||||
|
||||
@@ -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'])
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user