Skip to content

Commit 90cef43

Browse files
authored
Merge branch 'main' into zstd-dict-content-buffer
2 parents fe3fb49 + 2fd09b0 commit 90cef43

File tree

4 files changed

+84
-5
lines changed

4 files changed

+84
-5
lines changed

Doc/howto/free-threading-extensions.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ The wheels, shared libraries, and binaries are indicated by a ``t`` suffix.
396396
free-threaded build, with the ``t`` suffix, such as ``python3.13t``.
397397
* `pypa/cibuildwheel <https://github.com/pypa/cibuildwheel>`_ supports the
398398
free-threaded build if you set
399-
`CIBW_FREE_THREADED_SUPPORT <https://cibuildwheel.pypa.io/en/stable/options/#free-threaded-support>`_.
399+
`CIBW_ENABLE to cpython-freethreading <https://cibuildwheel.pypa.io/en/stable/options/#enable>`_.
400400

401401
Limited C API and Stable ABI
402402
............................

Lib/http/server.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -980,8 +980,8 @@ def test(HandlerClass=BaseHTTPRequestHandler,
980980
HandlerClass.protocol_version = protocol
981981

982982
if tls_cert:
983-
server = ThreadingHTTPSServer(addr, HandlerClass, certfile=tls_cert,
984-
keyfile=tls_key, password=tls_password)
983+
server = ServerClass(addr, HandlerClass, certfile=tls_cert,
984+
keyfile=tls_key, password=tls_password)
985985
else:
986986
server = ServerClass(addr, HandlerClass)
987987

@@ -1041,7 +1041,7 @@ def _main(args=None):
10411041
parser.error(f"Failed to read TLS password file: {e}")
10421042

10431043
# ensure dual-stack is not disabled; ref #38907
1044-
class DualStackServer(ThreadingHTTPServer):
1044+
class DualStackServerMixin:
10451045

10461046
def server_bind(self):
10471047
# suppress exception when protocol is IPv4
@@ -1054,9 +1054,16 @@ def finish_request(self, request, client_address):
10541054
self.RequestHandlerClass(request, client_address, self,
10551055
directory=args.directory)
10561056

1057+
class HTTPDualStackServer(DualStackServerMixin, ThreadingHTTPServer):
1058+
pass
1059+
class HTTPSDualStackServer(DualStackServerMixin, ThreadingHTTPSServer):
1060+
pass
1061+
1062+
ServerClass = HTTPSDualStackServer if args.tls_cert else HTTPDualStackServer
1063+
10571064
test(
10581065
HandlerClass=SimpleHTTPRequestHandler,
1059-
ServerClass=DualStackServer,
1066+
ServerClass=ServerClass,
10601067
port=args.port,
10611068
bind=args.bind,
10621069
protocol=args.protocol,

Lib/test/test_httpservers.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import html
2222
import http, http.client
2323
import urllib.parse
24+
import urllib.request
2425
import tempfile
2526
import time
2627
import datetime
@@ -33,6 +34,8 @@
3334
from test.support import (
3435
is_apple, import_helper, os_helper, threading_helper
3536
)
37+
from test.support.script_helper import kill_python, spawn_python
38+
from test.support.socket_helper import find_unused_port
3639

3740
try:
3841
import ssl
@@ -1452,6 +1455,73 @@ def test_unknown_flag(self, _):
14521455
self.assertIn('error', stderr.getvalue())
14531456

14541457

1458+
class CommandLineRunTimeTestCase(unittest.TestCase):
1459+
served_data = os.urandom(32)
1460+
served_filename = 'served_filename'
1461+
tls_cert = certdata_file('ssl_cert.pem')
1462+
tls_key = certdata_file('ssl_key.pem')
1463+
tls_password = b'somepass'
1464+
tls_password_file = 'ssl_key_password'
1465+
1466+
def setUp(self):
1467+
super().setUp()
1468+
server_dir_context = os_helper.temp_cwd()
1469+
server_dir = self.enterContext(server_dir_context)
1470+
with open(self.served_filename, 'wb') as f:
1471+
f.write(self.served_data)
1472+
with open(self.tls_password_file, 'wb') as f:
1473+
f.write(self.tls_password)
1474+
1475+
def fetch_file(self, path, context=None):
1476+
req = urllib.request.Request(path, method='GET')
1477+
with urllib.request.urlopen(req, context=context) as res:
1478+
return res.read()
1479+
1480+
def parse_cli_output(self, output):
1481+
match = re.search(r'Serving (HTTP|HTTPS) on (.+) port (\d+)', output)
1482+
if match is None:
1483+
return None, None, None
1484+
return match.group(1).lower(), match.group(2), int(match.group(3))
1485+
1486+
def wait_for_server(self, proc, protocol, bind, port):
1487+
"""Check that the server has been successfully started."""
1488+
line = proc.stdout.readline().strip()
1489+
if support.verbose:
1490+
print()
1491+
print('python -m http.server: ', line)
1492+
return self.parse_cli_output(line) == (protocol, bind, port)
1493+
1494+
def test_http_client(self):
1495+
bind, port = '127.0.0.1', find_unused_port()
1496+
proc = spawn_python('-u', '-m', 'http.server', str(port), '-b', bind,
1497+
bufsize=1, text=True)
1498+
self.addCleanup(kill_python, proc)
1499+
self.addCleanup(proc.terminate)
1500+
self.assertTrue(self.wait_for_server(proc, 'http', bind, port))
1501+
res = self.fetch_file(f'http://{bind}:{port}/{self.served_filename}')
1502+
self.assertEqual(res, self.served_data)
1503+
1504+
@unittest.skipIf(ssl is None, "requires ssl")
1505+
def test_https_client(self):
1506+
context = ssl.create_default_context()
1507+
# allow self-signed certificates
1508+
context.check_hostname = False
1509+
context.verify_mode = ssl.CERT_NONE
1510+
1511+
bind, port = '127.0.0.1', find_unused_port()
1512+
proc = spawn_python('-u', '-m', 'http.server', str(port), '-b', bind,
1513+
'--tls-cert', self.tls_cert,
1514+
'--tls-key', self.tls_key,
1515+
'--tls-password-file', self.tls_password_file,
1516+
bufsize=1, text=True)
1517+
self.addCleanup(kill_python, proc)
1518+
self.addCleanup(proc.terminate)
1519+
self.assertTrue(self.wait_for_server(proc, 'https', bind, port))
1520+
url = f'https://{bind}:{port}/{self.served_filename}'
1521+
res = self.fetch_file(url, context=context)
1522+
self.assertEqual(res, self.served_data)
1523+
1524+
14551525
def setUpModule():
14561526
unittest.addModuleCleanup(os.chdir, os.getcwd())
14571527

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:mod:`http.server`: Fix IPv6 address binding and
2+
:option:`--directory <http.server --directory>` handling when using HTTPS.

0 commit comments

Comments
 (0)