diff --git a/Doc/deprecations/pending-removal-in-3.18.rst b/Doc/deprecations/pending-removal-in-3.18.rst index 19113aab981bbc6..8ff202f9466c71d 100644 --- a/Doc/deprecations/pending-removal-in-3.18.rst +++ b/Doc/deprecations/pending-removal-in-3.18.rst @@ -16,3 +16,10 @@ Pending removal in Python 3.18 * ``import`` lines in :file:`{name}.pth` files are silently ignored. (Contributed by Barry Warsaw in :gh:`148641`.) + +* :mod:`http.client`: + + * :meth:`!http.client.HTTPMessage.getallmatchingheaders` has been deprecated + since Python 3.16. It has returned an empty list for every input since + Python 3.0; use :meth:`email.message.Message.get_all` instead. + (Contributed by Julian Soreavis in :gh:`153648`.) diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index da98f1ad6b9bc3b..451722c0a42ab33 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -657,6 +657,15 @@ New deprecations 3.9, now issues a deprecation warning on use. This property is slated for removal in 3.21. Use ``ast.Tuple.elts`` instead. +* :mod:`http.client`: + + * :meth:`!http.client.HTTPMessage.getallmatchingheaders` is now deprecated + and will be removed in Python 3.18. It has returned an empty list for + every input since Python 3.0, and its only user, the CGI handler, was + removed in Python 3.15. Use :meth:`email.message.Message.get_all` + instead. + (Contributed by Julian Soreavis in :gh:`153648`.) + * :mod:`struct`: * Soft-deprecated since Python 3.15, using ``'F'`` and ``'D'`` type codes are now diff --git a/Lib/http/client.py b/Lib/http/client.py index 7ef99e7201c005c..92a1b5c316bb380 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -195,8 +195,8 @@ def _strip_ipv6_iface(enc_name: bytes) -> bytes: class HTTPMessage(email.message.Message): # The getallmatchingheaders() method was only used by the CGI handler - # that was removed in Python 3.15. However, since the public API was not - # properly defined, it will be kept for backwards compatibility reasons. + # that was removed in Python 3.15. It has returned an empty list for every + # input since Python 3.0. def getallmatchingheaders(self, name): """Find all header lines matching a given header name. @@ -208,6 +208,15 @@ def getallmatchingheaders(self, name): occurrences are returned. Case is not important in the header name. """ + import warnings + warnings._deprecated( + "http.client.HTTPMessage.getallmatchingheaders", + message=( + "{name!r} is deprecated and slated for removal in Python " + "{remove}. Use email.message.Message.get_all() instead." + ), + remove=(3, 18), + ) name = name.lower() + ':' n = len(name) lst = [] diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 5b1d6e0aa520794..a65661131557c1d 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -507,6 +507,12 @@ def test_max_connection_trailers(self): response = conn.getresponse() self.assertEqual(response.read(), chunked_expected) + def test_getallmatchingheaders_deprecated(self): + message = client.parse_headers(io.BytesIO(b"Set-Cookie: a=1\r\n\r\n")) + with self.assertWarns(DeprecationWarning): + message.getallmatchingheaders("Set-Cookie") + + class HttpMethodTests(TestCase): def test_invalid_method_names(self): methods = ( diff --git a/Misc/NEWS.d/next/Library/2026-07-13-08-20-16.gh-issue-153648.0L8KTV.rst b/Misc/NEWS.d/next/Library/2026-07-13-08-20-16.gh-issue-153648.0L8KTV.rst new file mode 100644 index 000000000000000..777db65be895c08 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-13-08-20-16.gh-issue-153648.0L8KTV.rst @@ -0,0 +1,4 @@ +Deprecate :meth:`!http.client.HTTPMessage.getallmatchingheaders`, to be +removed in Python 3.18. It has returned an empty list for every input since +Python 3.0, and its only user, the CGI handler, was removed in Python 3.15. +Use :meth:`email.message.Message.get_all` instead. Patch by Julian Soreavis.