Code

Ticket #7735: ticket7735.diff

File ticket7735.diff, 9.3 KB (added by lrekucki, 3 years ago)

Updated patch: Use "[200::addr:1]:port" format for IPv6 and detect it. Enable ipv6 in testserver.

Line 
1diff --git a/django/core/management/commands/runserver.py b/django/core/management/commands/runserver.py
2index 49e270d..618fa4d 100644
3--- a/django/core/management/commands/runserver.py
4+++ b/django/core/management/commands/runserver.py
5@@ -1,12 +1,19 @@
6 from optparse import make_option
7 import os
8+import socket
9 import sys
10 import warnings
11+import re
12 
13 from django.core.management.base import BaseCommand, CommandError
14 
15+naiveip_re = r'^(?:(?P<addr>\d{1,3}(?:\.\d{1,3}){3}|\[[a-fA-F0-9:]+\]):)?(?P<port>\d+)$'
16+DEFAULT_PORT = "8000"
17+
18 class Command(BaseCommand):
19     option_list = BaseCommand.option_list + (
20+        make_option('--ipv6', '-6', action='store_true', dest='enable_ipv6', default=False,
21+            help='Force the use of IPv6 address.'),
22         make_option('--noreload', action='store_false', dest='use_reloader', default=True,
23             help='Tells Django to NOT use the auto-reloader.'),
24         make_option('--nostatic', action="store_false", dest='use_static_handler', default=True,
25@@ -27,22 +34,30 @@ class Command(BaseCommand):
26         from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
27         from django.core.handlers.wsgi import WSGIHandler
28         from django.contrib.staticfiles.handlers import StaticFilesHandler
29+        enable_ipv6 = options.get('enable_ipv6')
30+        if enable_ipv6 and not hasattr(socket, 'AF_INET6'):
31+            raise CommandError("Your Python does not support IPv6.")
32+
33         if args:
34             raise CommandError('Usage is runserver %s' % self.args)
35         if not addrport:
36             addr = ''
37-            port = '8000'
38+            port = DEFAULT_PORT
39         else:
40-            try:
41-                addr, port = addrport.split(':')
42-            except ValueError:
43-                addr, port = '', addrport
44+            m = re.match(naiveip_re, addrport)
45+            if m is None:
46+                raise CommandError("%r is not a valid port number or address:port pair." % addrport)
47+            addr, port = m.groups()
48+            if not port.isdigit():
49+                raise CommandError("%r is not a valid port number." % port)
50+            if addr:
51+                if addr[0] == '[' and addr[-1] == ']':
52+                    enable_ipv6 = True
53+                    addr = addr[1:-1]
54+                elif enable_ipv6:
55+                    raise CommandError("IPv6 addresses must be surrounded with brackets")
56         if not addr:
57-            addr = '127.0.0.1'
58-
59-        if not port.isdigit():
60-            raise CommandError("%r is not a valid port number." % port)
61-
62+            addr = (enable_ipv6 and '::1') or '127.0.0.1'
63         use_reloader = options.get('use_reloader', True)
64         admin_media_path = options.get('admin_media_path', '')
65         shutdown_message = options.get('shutdown_message', '')
66@@ -56,7 +71,8 @@ class Command(BaseCommand):
67             print "Validating models..."
68             self.validate(display_num_errors=True)
69             print "\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE)
70-            print "Development server is running at http://%s:%s/" % (addr, port)
71+            fmt_addr = (enable_ipv6 and '[%s]' % addr) or addr
72+            print "Development server is running at http://%s:%s/" % (fmt_addr, port)
73             print "Quit the server with %s." % quit_command
74 
75             # django.core.management.base forces the locale to en-us. We should
76@@ -73,7 +89,7 @@ class Command(BaseCommand):
77                     handler = StaticFilesHandler(handler)
78                 # serve admin media like old-school (deprecation pending)
79                 handler = AdminMediaHandler(handler, admin_media_path)
80-                run(addr, int(port), handler)
81+                run(addr, int(port), handler, enable_ipv6=enable_ipv6)
82             except WSGIServerException, e:
83                 # Use helpful error messages instead of ugly tracebacks.
84                 ERRORS = {
85diff --git a/django/core/management/commands/testserver.py b/django/core/management/commands/testserver.py
86index d3d9698..be5b9ea 100644
87--- a/django/core/management/commands/testserver.py
88+++ b/django/core/management/commands/testserver.py
89@@ -9,6 +9,8 @@ class Command(BaseCommand):
90         make_option('--addrport', action='store', dest='addrport',
91             type='string', default='',
92             help='port number or ipaddr:port to run the server on'),
93+        make_option('--ipv6', '-6', action='store_true', dest='enable_ipv6', default=False,
94+            help='Forces IPv6 support.'),
95     )
96     help = 'Runs a development server with data from the given fixture(s).'
97     args = '[fixture ...]'
98@@ -33,4 +35,4 @@ class Command(BaseCommand):
99         # a strange error -- it causes this handle() method to be called
100         # multiple times.
101         shutdown_message = '\nServer stopped.\nNote that the test database, %r, has not been deleted. You can explore it on your own.' % db_name
102-        call_command('runserver', addrport=addrport, shutdown_message=shutdown_message, use_reloader=False)
103+        call_command('runserver', addrport=addrport, shutdown_message=shutdown_message, use_reloader=False, enable_ipv6=options['enable_ipv6'])
104diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py
105index 9c92a88..35bb990 100644
106--- a/django/core/servers/basehttp.py
107+++ b/django/core/servers/basehttp.py
108@@ -10,6 +10,7 @@ been reviewed for security issues. Don't use it for production use.
109 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
110 import os
111 import re
112+import socket
113 import sys
114 import urllib
115 import warnings
116@@ -678,9 +679,12 @@ class AdminMediaHandler(StaticFilesHandler):
117         """
118         return path.startswith(self.media_url[2]) and not self.media_url[1]
119 
120+class WSGIServerV6(WSGIServer):
121+    address_family = socket.AF_INET6
122 
123-def run(addr, port, wsgi_handler):
124+def run(addr, port, wsgi_handler, enable_ipv6=False):
125     server_address = (addr, port)
126-    httpd = WSGIServer(server_address, WSGIRequestHandler)
127+    server_class = (enable_ipv6 and WSGIServerV6) or WSGIServer
128+    httpd = server_class(server_address, WSGIRequestHandler)
129     httpd.set_app(wsgi_handler)
130     httpd.serve_forever()
131diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt
132index 14fc69f..0570fcb 100644
133--- a/docs/ref/django-admin.txt
134+++ b/docs/ref/django-admin.txt
135@@ -630,7 +630,7 @@ runserver [port or ipaddr:port]
136 .. django-admin:: runserver
137 
138 Starts a lightweight development Web server on the local machine. By default,
139-the server runs on port 8000 on the IP address 127.0.0.1. You can pass in an
140+the server runs on port 8000 on the IP address ``127.0.0.1``. You can pass in an
141 IP address and port number explicitly.
142 
143 If you run this script as a user with normal privileges (recommended), you
144@@ -654,10 +654,15 @@ them to standard output, but it won't stop the server.
145 You can run as many servers as you want, as long as they're on separate ports.
146 Just execute ``django-admin.py runserver`` more than once.
147 
148-Note that the default IP address, 127.0.0.1, is not accessible from other
149+Note that the default IP address, ``127.0.0.1``, is not accessible from other
150 machines on your network. To make your development server viewable to other
151 machines on the network, use its own IP address (e.g. ``192.168.2.1``) or
152-``0.0.0.0``.
153+``0.0.0.0`` or ``::`` (with IPv6 enabled).
154+
155+.. versionchanged:: 1.3
156+
157+You can also provide an IPv6 address surrounded by brackets
158+(eg. ``[200a::1]:8000``). This will automaticaly enable IPv6 support.
159 
160 .. django-admin-option:: --adminmedia
161 
162@@ -706,25 +711,49 @@ Example usage::
163 
164     django-admin.py runserver --insecure
165 
166+.. django-admin-option:: --ipv6, -6
167+
168+.. versionadded:: 1.3
169+
170+Use the ``--ipv6`` (or shorter ``-6``) option to tell Django to use IPv6 for
171+the development server. This changes the default IP address from
172+``127.0.0.1`` to ``::1``.
173+
174+Example usage::
175+
176+    django-admin.py runserver --ipv6
177+
178 Examples of using different ports and addresses
179 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
180 
181-Port 8000 on IP address 127.0.0.1::
182+Port 8000 on IP address ``127.0.0.1``::
183 
184-       django-admin.py runserver
185+    django-admin.py runserver
186 
187-Port 8000 on IP address 1.2.3.4::
188+Port 8000 on IP address ``1.2.3.4``::
189 
190-       django-admin.py runserver 1.2.3.4:8000
191+    django-admin.py runserver 1.2.3.4:8000
192 
193-Port 7000 on IP address 127.0.0.1::
194+Port 7000 on IP address ``127.0.0.1``::
195 
196     django-admin.py runserver 7000
197 
198-Port 7000 on IP address 1.2.3.4::
199+Port 7000 on IP address ``1.2.3.4``::
200 
201     django-admin.py runserver 1.2.3.4:7000
202 
203+Port 8000 on IPv6 address ``::1``::
204+
205+    django-admin.py runserver -6
206+
207+Port 7000 on IPv6 address ``::1``::
208+
209+    django-admin.py runserver -6 7000
210+
211+Port 7000 on IPv6 address ``2001:0db8:1234:5678::9``::
212+
213+    django-admin.py runserver [2001:0db8:1234:5678::9]:7000
214+
215 Serving static files with the development server
216 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
217 
218@@ -988,7 +1017,7 @@ templates.
219 .. django-admin-option:: --addrport [port number or ipaddr:port]
220 
221 Use ``--addrport`` to specify a different port, or IP address and port, from
222-the default of 127.0.0.1:8000. This value follows exactly the same format and
223+the default of ``127.0.0.1:8000``. This value follows exactly the same format and
224 serves exactly the same function as the argument to the ``runserver`` command.
225 
226 Examples: