self.log_message("CGI script exited OK")
+def _get_best_family(*address):
+ infos = socket.getaddrinfo(
+ *address,
+ type=socket.SOCK_STREAM,
+ flags=socket.AI_PASSIVE,
+ )
+ family, type, proto, canonname, sockaddr = next(iter(infos))
+ return family, sockaddr
+
+
def test(HandlerClass=BaseHTTPRequestHandler,
ServerClass=ThreadingHTTPServer,
- protocol="HTTP/1.0", port=8000, bind=""):
+ protocol="HTTP/1.0", port=8000, bind=None):
"""Test the HTTP request handler class.
This runs an HTTP server on port 8000 (or the port argument).
"""
- server_address = (bind, port)
-
- if ':' in bind:
- ServerClass.address_family = socket.AF_INET6
+ ServerClass.address_family, addr = _get_best_family(bind, port)
HandlerClass.protocol_version = protocol
- with ServerClass(server_address, HandlerClass) as httpd:
- sa = httpd.socket.getsockname()
- serve_message = "Serving HTTP on {host} port {port} (http://{host}:{port}/) ..."
- print(serve_message.format(host=sa[0], port=sa[1]))
+ with ServerClass(addr, HandlerClass) as httpd:
+ host, port = httpd.socket.getsockname()[:2]
+ url_host = f'[{host}]' if ':' in host else host
+ print(
+ f"Serving HTTP on {host} port {port} "
+ f"(http://{url_host}:{port}/) ..."
+ )
try:
httpd.serve_forever()
except KeyboardInterrupt:
parser = argparse.ArgumentParser()
parser.add_argument('--cgi', action='store_true',
help='Run as CGI Server')
- parser.add_argument('--bind', '-b', default='', metavar='ADDRESS',
+ parser.add_argument('--bind', '-b', metavar='ADDRESS',
help='Specify alternate bind address '
'[default: all interfaces]')
parser.add_argument('--directory', '-d', default=os.getcwd(),
class ScriptTestCase(unittest.TestCase):
+
+ def mock_server_class(self):
+ return mock.MagicMock(
+ return_value=mock.MagicMock(
+ __enter__=mock.MagicMock(
+ return_value=mock.MagicMock(
+ socket=mock.MagicMock(
+ getsockname=lambda: ('', 0),
+ ),
+ ),
+ ),
+ ),
+ )
+
+ @mock.patch('builtins.print')
+ def test_server_test_unspec(self, _):
+ mock_server = self.mock_server_class()
+ server.test(ServerClass=mock_server, bind=None)
+ self.assertIn(
+ mock_server.address_family,
+ (socket.AF_INET6, socket.AF_INET),
+ )
+
+ @mock.patch('builtins.print')
+ def test_server_test_localhost(self, _):
+ mock_server = self.mock_server_class()
+ server.test(ServerClass=mock_server, bind="localhost")
+ self.assertIn(
+ mock_server.address_family,
+ (socket.AF_INET6, socket.AF_INET),
+ )
+
+ ipv6_addrs = (
+ "::",
+ "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
+ "::1",
+ )
+
+ ipv4_addrs = (
+ "0.0.0.0",
+ "8.8.8.8",
+ "127.0.0.1",
+ )
+
@mock.patch('builtins.print')
def test_server_test_ipv6(self, _):
- mock_server = mock.MagicMock()
- server.test(ServerClass=mock_server, bind="::")
- self.assertEqual(mock_server.address_family, socket.AF_INET6)
-
- mock_server.reset_mock()
- server.test(ServerClass=mock_server,
- bind="2001:0db8:85a3:0000:0000:8a2e:0370:7334")
- self.assertEqual(mock_server.address_family, socket.AF_INET6)
-
- mock_server.reset_mock()
- server.test(ServerClass=mock_server,
- bind="::1")
- self.assertEqual(mock_server.address_family, socket.AF_INET6)
+ for bind in self.ipv6_addrs:
+ mock_server = self.mock_server_class()
+ server.test(ServerClass=mock_server, bind=bind)
+ self.assertEqual(mock_server.address_family, socket.AF_INET6)
+
+ @mock.patch('builtins.print')
+ def test_server_test_ipv4(self, _):
+ for bind in self.ipv4_addrs:
+ mock_server = self.mock_server_class()
+ server.test(ServerClass=mock_server, bind=bind)
+ self.assertEqual(mock_server.address_family, socket.AF_INET)
def test_main(verbose=None):