Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #7735 -- Added support for IPv6 adresses to runserver and tests…

…erver 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
  • Loading branch information...
commit 6a32e253f68b62b75d787f698ebaef461886c21c 1 parent 132afbf
@jezdez jezdez authored
View
40 django/core/management/commands/runserver.py
@@ -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 @@ def get_handler(self, *args, **options):
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 @@ def inner_run(self, *args, **options):
) % {
"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 @@ def inner_run(self, *args, **options):
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
4 django/core/management/commands/testserver.py
@@ -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 @@ def handle(self, *fixture_labels, **options):
# 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
11 django/core/servers/basehttp.py
@@ -10,6 +10,7 @@
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 @@ def _should_handle(self, path):
"""
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()
View
5 docs/man/django-admin.1
@@ -75,7 +75,7 @@ Runs this project as a FastCGI application. Requires flup. Use
.B runfcgi help
for help on the KEY=val pairs.
.TP
-.BI "runserver [" "\-\-noreload" "] [" "\-\-nostatic" "] [" "\-\-insecure" "] [" "\-\-adminmedia=ADMIN_MEDIA_PATH" "] [" "port|ipaddr:port" "]"
+.BI "runserver [" "\-\-noreload" "] [" "\-\-nostatic" "] [" "\-\-insecure" "] [" "\-\-ipv6" "] [" "\-\-adminmedia=ADMIN_MEDIA_PATH" "] [" "port|ipaddr:port" "]"
Starts a lightweight Web server for development.
.TP
.BI "shell [" "\-\-plain" "]"
@@ -170,6 +170,9 @@ Disable automatic serving of static files from STATIC_URL.
.I \-\-insecure
Enables serving of static files even if DEBUG is False.
.TP
+.I \-\-ipv6
+Enables IPv6 addresses.
+.TP
.I \-\-verbosity=VERBOSITY
Verbosity level: 0=minimal output, 1=normal output, 2=all output.
.TP
View
49 docs/ref/django-admin.txt
@@ -630,7 +630,7 @@ runserver [port or ipaddr:port]
.. django-admin:: runserver
Starts a lightweight development Web server on the local machine. By default,
-the server runs on port 8000 on the IP address 127.0.0.1. You can pass in an
+the server runs on port 8000 on the IP address ``127.0.0.1``. You can pass in an
IP address and port number explicitly.
If you run this script as a user with normal privileges (recommended), you
@@ -654,10 +654,15 @@ them to standard output, but it won't stop the server.
You can run as many servers as you want, as long as they're on separate ports.
Just execute ``django-admin.py runserver`` more than once.
-Note that the default IP address, 127.0.0.1, is not accessible from other
+Note that the default IP address, ``127.0.0.1``, is not accessible from other
machines on your network. To make your development server viewable to other
machines on the network, use its own IP address (e.g. ``192.168.2.1``) or
-``0.0.0.0``.
+``0.0.0.0`` or ``::`` (with IPv6 enabled).
+
+.. versionchanged:: 1.3
+
+You can also provide an IPv6 address surrounded by brackets
+(eg. ``[200a::1]:8000``). This will automaticaly enable IPv6 support.
.. django-admin-option:: --adminmedia
@@ -681,25 +686,49 @@ Example usage::
django-admin.py runserver --noreload
+.. django-admin-option:: --ipv6, -6
+
+.. versionadded:: 1.3
+
+Use the ``--ipv6`` (or shorter ``-6``) option to tell Django to use IPv6 for
+the development server. This changes the default IP address from
+``127.0.0.1`` to ``::1``.
+
+Example usage::
+
+ django-admin.py runserver --ipv6
+
Examples of using different ports and addresses
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Port 8000 on IP address 127.0.0.1::
+Port 8000 on IP address ``127.0.0.1``::
- django-admin.py runserver
+ django-admin.py runserver
-Port 8000 on IP address 1.2.3.4::
+Port 8000 on IP address ``1.2.3.4``::
- django-admin.py runserver 1.2.3.4:8000
+ django-admin.py runserver 1.2.3.4:8000
-Port 7000 on IP address 127.0.0.1::
+Port 7000 on IP address ``127.0.0.1``::
django-admin.py runserver 7000
-Port 7000 on IP address 1.2.3.4::
+Port 7000 on IP address ``1.2.3.4``::
django-admin.py runserver 1.2.3.4:7000
+Port 8000 on IPv6 address ``::1``::
+
+ django-admin.py runserver -6
+
+Port 7000 on IPv6 address ``::1``::
+
+ django-admin.py runserver -6 7000
+
+Port 7000 on IPv6 address ``2001:0db8:1234:5678::9``::
+
+ django-admin.py runserver [2001:0db8:1234:5678::9]:7000
+
Serving static files with the development server
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -963,7 +992,7 @@ templates.
.. django-admin-option:: --addrport [port number or ipaddr:port]
Use ``--addrport`` to specify a different port, or IP address and port, from
-the default of 127.0.0.1:8000. This value follows exactly the same format and
+the default of ``127.0.0.1:8000``. This value follows exactly the same format and
serves exactly the same function as the argument to the ``runserver`` command.
Examples:
Please sign in to comment.
Something went wrong with that request. Please try again.