Skip to content

Commit 2677eb9

Browse files
committed
add ipv6 support to built-in django runserver, backported from
https://code.djangoproject.com/ticket/7735 include arguments in runserver, so that --ip6 can be passed in - Legacy-Id: 5419
1 parent b902276 commit 2677eb9

4 files changed

Lines changed: 40 additions & 14 deletions

File tree

v4.41/django/core/management/commands/runserver.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
from django.core.management.base import BaseCommand, CommandError
22
from optparse import make_option
33
import os
4+
import socket
45
import sys
6+
import re
7+
8+
naiveip_re = r'^(?:(?P<addr>\d{1,3}(?:\.\d{1,3}){3}|\[[a-fA-F0-9:]+\]):)?(?P<port>\d+)$'
9+
DEFAULT_PORT = "8000"
510

611
class Command(BaseCommand):
712
option_list = BaseCommand.option_list + (
13+
make_option('--ipv6', '-6', action='store_true', dest='enable_ipv6', default=False,
14+
help='Force the use of IPv6 address.'),
815
make_option('--noreload', action='store_false', dest='use_reloader', default=True,
916
help='Tells Django to NOT use the auto-reloader.'),
1017
make_option('--adminmedia', dest='admin_media_path', default='',
@@ -20,21 +27,32 @@ def handle(self, addrport='', *args, **options):
2027
import django
2128
from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
2229
from django.core.handlers.wsgi import WSGIHandler
30+
enable_ipv6 = options.get('enable_ipv6')
31+
if enable_ipv6 and not hasattr(socket, 'AF_INET6'):
32+
raise CommandError("Your Python does not support IPv6.")
33+
2334
if args:
2435
raise CommandError('Usage is runserver %s' % self.args)
2536
if not addrport:
2637
addr = ''
27-
port = '8000'
38+
port = DEFAULT_PORT
2839
else:
29-
try:
30-
addr, port = addrport.split(':')
31-
except ValueError:
32-
addr, port = '', addrport
33-
if not addr:
34-
addr = '127.0.0.1'
35-
40+
m = re.match(naiveip_re, addrport)
41+
if m is None:
42+
raise CommandError("%r is not a valid port number or address:port pair." % addrport)
43+
addr, port = m.groups()
44+
3645
if not port.isdigit():
3746
raise CommandError("%r is not a valid port number." % port)
47+
if addr:
48+
if addr[0] == '[' and addr[-1] == ']':
49+
enable_ipv6 = True
50+
addr = addr[1:-1]
51+
elif enable_ipv6:
52+
raise CommandError("IPv6 addresses must be surrounded with brackets")
53+
if not addr:
54+
addr = '127.0.0.1'
55+
addr = (enable_ipv6 and '::1') or '127.0.0.1'
3856

3957
use_reloader = options.get('use_reloader', True)
4058
admin_media_path = options.get('admin_media_path', '')
@@ -47,7 +65,8 @@ def inner_run():
4765
print "Validating models..."
4866
self.validate(display_num_errors=True)
4967
print "\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE)
50-
print "Development server is running at http://%s:%s/" % (addr, port)
68+
fmt_addr = (enable_ipv6 and '[%s]' % addr) or addr
69+
print "Development server is running at http://%s:%s/" % (fmt_addr, port)
5170
print "Quit the server with %s." % quit_command
5271

5372
# django.core.management.base forces the locale to en-us. We should
@@ -57,7 +76,7 @@ def inner_run():
5776

5877
try:
5978
handler = AdminMediaHandler(WSGIHandler(), admin_media_path)
60-
run(addr, int(port), handler)
79+
run(addr, int(port), handler, enable_ipv6=enable_ipv6)
6180
except WSGIServerException, e:
6281
# Use helpful error messages instead of ugly tracebacks.
6382
ERRORS = {

v4.41/django/core/management/commands/testserver.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ class Command(BaseCommand):
77
make_option('--addrport', action='store', dest='addrport',
88
type='string', default='',
99
help='port number or ipaddr:port to run the server on'),
10+
make_option('--ipv6', '-6', action='store_true', dest='enable_ipv6', default=False,
11+
help='Forces IPv6 support.'),
1012
)
1113
help = 'Runs a development server with data from the given fixture(s).'
1214
args = '[fixture ...]'
@@ -30,4 +32,4 @@ def handle(self, *fixture_labels, **options):
3032
# a strange error -- it causes this handle() method to be called
3133
# multiple times.
3234
shutdown_message = '\nServer stopped.\nNote that the test database, %r, has not been deleted. You can explore it on your own.' % db_name
33-
call_command('runserver', addrport=addrport, shutdown_message=shutdown_message, use_reloader=False)
35+
call_command('runserver', addrport=addrport, shutdown_message=shutdown_message, use_reloader=False, enable_ipv6=options['enable_ipv6'])

v4.41/django/core/servers/basehttp.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import mimetypes
1212
import os
1313
import re
14+
import socket
1415
import stat
1516
import sys
1617
import urllib
@@ -714,8 +715,12 @@ def __call__(self, environ, start_response):
714715
start_response(status, headers.items())
715716
return output
716717

717-
def run(addr, port, wsgi_handler):
718+
class WSGIServerV6(WSGIServer):
719+
address_family = socket.AF_INET6
720+
721+
def run(addr, port, wsgi_handler, enable_ipv6=False):
718722
server_address = (addr, port)
719-
httpd = WSGIServer(server_address, WSGIRequestHandler)
723+
server_class = (enable_ipv6 and WSGIServerV6) or WSGIServer
724+
httpd = server_class(server_address, WSGIRequestHandler)
720725
httpd.set_app(wsgi_handler)
721726
httpd.serve_forever()

v4.41/runserver

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#!/bin/sh
22

3-
REMOTE_USER=admin ./manage runserver
3+
REMOTE_USER=admin ./manage runserver $*

0 commit comments

Comments
 (0)