falconry / falcon

The no-magic web data plane API and microservices framework for Python developers, with a focus on reliability, correctness, and performance at scale.
https://falcon.readthedocs.io/en/stable/
Apache License 2.0
9.53k stars 945 forks source link

IPv6 WSGI server fails to start #2186

Closed ddundi0 closed 1 year ago

ddundi0 commented 1 year ago

Hi,

I've been using falcon3.1.1 and trying to start the server on an IPv6 machine. Whatever I've tried, starting the server listening on all interfaces ('::'), or providing the actually address of the NI, it always immediately fails to start with the socket.gaierror and an "Address family for hostname not supported" exception message.

Here's the full stack trace;

> Traceback (most recent call last):
  File "//program.py", line 33, in <module>
    with make_server('::', 8000, app) as httpd:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/wsgiref/simple_server.py", line 154, in make_server
    server = server_class((host, port), handler_class)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/socketserver.py", line 456, in __init__
    self.server_bind()
  File "/usr/lib64/python3.11/wsgiref/simple_server.py", line 50, in server_bind
    HTTPServer.server_bind(self)
  File "/usr/lib64/python3.11/http/server.py", line 136, in server_bind
    socketserver.TCPServer.server_bind(self)
  File "/usr/lib64/python3.11/socketserver.py", line 472, in server_bind
    self.socket.bind(self.server_address)
socket.gaierror: [Errno -9] Address family for hostname not supported

It's enough to take the WSGI Quickstart example and provide the '::' Ipv6 address for starting the server, but anyways here's the CP of the full code.

from wsgiref.simple_server import make_server

import falcon

class ThingsResource:
    def on_get(self, req, resp):
        resp.status = falcon.HTTP_200  # This is the default status
        resp.content_type = falcon.MEDIA_TEXT  # Default is JSON, so override
        resp.text = (
            '\nTwo things awe me most, the starry sky '
            'above me and the moral law within me.\n'
            '\n'
            '    ~ Immanuel Kant\n\n'
        )

app = falcon.App()

things = ThingsResource()

app.add_route('/things', things)

if __name__ == '__main__':
    with make_server('::', 8000, app) as httpd:
        print('Serving on port 8000...')
        httpd.serve_forever()`

Am I missing something here ? Does falcon library expose the possibility to configure address_family to something like "socket.AF_INET6".

Also, when trying to start it on a specific address and using the python's socket API to get that address' info, the "socket.getaddrinfo" call is successful, returning something like this;

>  [(<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('2002:14ba:9ea:8800:9c7b:4e6c:dae2:741c', 8080, 0, 0)), (<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_DGRAM: 2>, 17, '', ('2002:14ba:9ea:8800:9c7b:4e6c:dae2:741c', 8080, 0, 0)), (<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_RAW: 3>, 0, '', ('2002:14ba:9ea:8800:9c7b:4e6c:dae2:741c', 8080, 0, 0))]

But starting the server on that same IP just won't work.