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:
parent
132afbf8ee
commit
6a32e253f6
|
@ -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
|
||||
if not self.addr:
|
||||
self.addr = '127.0.0.1'
|
||||
|
||||
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 = 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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
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
|
||||
|
||||
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:
|
||||
|
|
Loading…
Reference in New Issue