37

Does http.server (http being a Python 3.x module) support ipv6? For instance, using this command-line code (which starts a webserver):

python -m http.server [port]
Brōtsyorfuzthrāx
  • 4,387
  • 4
  • 34
  • 56
  • 2
    Use `netstat -l` to see if it's binding to the port on an IPv6 address. If it is then, "yes it's supported". – user2864740 Sep 12 '14 at 22:38
  • How do you interpret the results? I don't even see the port number I'm connecting to listed there (or any mention of IPv6). – Brōtsyorfuzthrāx Sep 12 '14 at 23:13
  • 1
    Also use the `-n` option, does that make the output more useful? IPv6 addresses can be identified by looking different from the IPv4 counterparts - if a server listens to a port on both IPv6 and IPv4 there will be two entries displayed. The listen-all-IPs value for IPv4 is 0.0.0.0 and for IPv6 it is ::0. (And if the port is not displayed after that then the server is not currently running/listening at all.) – user2864740 Sep 12 '14 at 23:16
  • Thanks! I just see the IPv4-style (`tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN`). So, I guess that means it doesn't support IPv6. You should condense all this into an answer so I can accept it, if you want. – Brōtsyorfuzthrāx Sep 13 '14 at 01:36
  • The tornado module works for IPv6 with a webserver in Python (I saw that it did, but I tested it with your method, and it shows up twice, in both formats.) – Brōtsyorfuzthrāx Sep 13 '14 at 01:57
  • 2
    But it isn't an answer :( It just says that it isn't currently listening on IPv6; not that it can't. There might be an option, etc., or it might simply be the network interface isn't setup for IPv6. – user2864740 Sep 13 '14 at 01:58
  • I think you're right, actually. I looked at the source code to `client.py` which is part of the `http` module, and I see references to IPv6 and how to handle it. So, I suppose it must be possible, somehow. – Brōtsyorfuzthrāx Sep 13 '14 at 02:03
  • 2
    There's no reason this shouldn't work. The underlying code obviously supports it. Time to file a feature request. – Michael Hampton Sep 23 '14 at 18:04

4 Answers4

51

Starting with Python 3.8, python -m http.server supports IPv6 (see documentation and bug report with implementation history).

To listen on all all available interfaces:

python -m http.server --bind ::

Python 3.8 is was released on 2019-10-14.

sebas
  • 1,283
  • 1
  • 12
  • 16
17

Yes, it does. When defining your server, do it like this, as seen here.

import socket
from http.server import HTTPServer

class HTTPServerV6(HTTPServer):
    address_family = socket.AF_INET6

and then listen like this:

server = HTTPServerV6(('::', 8080), MyHandler)
server.serve_forever()
asynts
  • 2,213
  • 2
  • 21
  • 35
Oliver Bock
  • 4,829
  • 5
  • 38
  • 62
  • Sadly it seems difficult to make the built-in HTTP server handle both IPv6 and IPv4 connections. – Oliver Bock Sep 18 '15 at 07:14
  • 4
    An IPv6 stack handles IPv4 connections as long as the passive socket isn't bound to a specific v6 address (!= in6addr_any, an empty string of "::") or the option IPv6_ONLY is set. – Martin Richard May 30 '16 at 09:05
  • 1
    In case anyone is trying to replicate the default `python -m http.server` behavior of serving the current working directory, you can do that by changing two lines. `from http.server import HTTPServer, SimpleHTTPRequestHandler` and `server = HTTPServerV6(('::', 8080), SimpleHTTPRequestHandler)` – paul Feb 11 '22 at 12:43
9

There is a patch to allow IPv6 bind in http.server in Python 3. I tried it, finding it works on my laptop. Please visit https://bugs.python.org/issue24209 for more info. Or just do as following:

Add the lines after + to the file /your/path/to/python/Lib/http/server.py. Please note lines without + are the original code of server.py.

    server_address = (bind, port)

+   if ':' in bind:
+       ServerClass.address_family = socket.AF_INET6
+        
    HandlerClass.protocal_version = protocol    
    httpd = ServerClass(server_address, HandlerClass)

Then try:

python -m http.server -b *your-ipv6-addr* *your-port*
tjanson
  • 1,471
  • 12
  • 12
Edward Zhang
  • 117
  • 1
  • 2
0

The Python 3 version (until 3.8) of Oliver Bock does look like this:

myserver.py:

from http.server import HTTPServer
from http.server import SimpleHTTPRequestHandler
import socket

class HTTPServerV6(HTTPServer):
    address_family = socket.AF_INET6

server = HTTPServerV6(('::', 8080), SimpleHTTPRequestHandler)
server.serve_forever()

Modifying your internal Python 3 files like Edward Zhang seems rather extreme.

DSchmidt
  • 1,095
  • 9
  • 14