Commit af00c6c2 authored by Benjamin Peterson's avatar Benjamin Peterson

add context parameter to HTTPHandler (closes #22788)

parent 3a0f8786
...@@ -839,17 +839,22 @@ supports sending logging messages to a Web server, using either ``GET`` or ...@@ -839,17 +839,22 @@ supports sending logging messages to a Web server, using either ``GET`` or
``POST`` semantics. ``POST`` semantics.
.. class:: HTTPHandler(host, url, method='GET', secure=False, credentials=None) .. class:: HTTPHandler(host, url, method='GET', secure=False, credentials=None, context=None)
Returns a new instance of the :class:`HTTPHandler` class. The *host* can be Returns a new instance of the :class:`HTTPHandler` class. The *host* can be
of the form ``host:port``, should you need to use a specific port number. of the form ``host:port``, should you need to use a specific port number. If
If no *method* is specified, ``GET`` is used. If *secure* is true, an HTTPS no *method* is specified, ``GET`` is used. If *secure* is true, a HTTPS
connection will be used. If *credentials* is specified, it should be a connection will be used. The *context* parameter may be set to a
2-tuple consisting of userid and password, which will be placed in an HTTP :class:`ssl.SSLContext` instance to configure the SSL settings used for the
HTTPS connection. If *credentials* is specified, it should be a 2-tuple
consisting of userid and password, which will be placed in a HTTP
'Authorization' header using Basic authentication. If you specify 'Authorization' header using Basic authentication. If you specify
credentials, you should also specify secure=True so that your userid and credentials, you should also specify secure=True so that your userid and
password are not passed in cleartext across the wire. password are not passed in cleartext across the wire.
.. versionchanged:: 3.4.3
The *context* parameter was added.
.. method:: mapLogRecord(record) .. method:: mapLogRecord(record)
Provides a dictionary, based on ``record``, which is to be URL-encoded Provides a dictionary, based on ``record``, which is to be URL-encoded
......
...@@ -1089,7 +1089,8 @@ class HTTPHandler(logging.Handler): ...@@ -1089,7 +1089,8 @@ class HTTPHandler(logging.Handler):
A class which sends records to a Web server, using either GET or A class which sends records to a Web server, using either GET or
POST semantics. POST semantics.
""" """
def __init__(self, host, url, method="GET", secure=False, credentials=None): def __init__(self, host, url, method="GET", secure=False, credentials=None,
context=None):
""" """
Initialize the instance with the host, the request URL, and the method Initialize the instance with the host, the request URL, and the method
("GET" or "POST") ("GET" or "POST")
...@@ -1098,11 +1099,15 @@ class HTTPHandler(logging.Handler): ...@@ -1098,11 +1099,15 @@ class HTTPHandler(logging.Handler):
method = method.upper() method = method.upper()
if method not in ["GET", "POST"]: if method not in ["GET", "POST"]:
raise ValueError("method must be GET or POST") raise ValueError("method must be GET or POST")
if not secure and context is not None:
raise ValueError("context parameter only makes sense "
"with secure=True")
self.host = host self.host = host
self.url = url self.url = url
self.method = method self.method = method
self.secure = secure self.secure = secure
self.credentials = credentials self.credentials = credentials
self.context = context
def mapLogRecord(self, record): def mapLogRecord(self, record):
""" """
...@@ -1122,7 +1127,7 @@ class HTTPHandler(logging.Handler): ...@@ -1122,7 +1127,7 @@ class HTTPHandler(logging.Handler):
import http.client, urllib.parse import http.client, urllib.parse
host = self.host host = self.host
if self.secure: if self.secure:
h = http.client.HTTPSConnection(host) h = http.client.HTTPSConnection(host, context=self.context)
else: else:
h = http.client.HTTPConnection(host) h = http.client.HTTPConnection(host)
url = self.url url = self.url
......
...@@ -1667,21 +1667,11 @@ class HTTPHandlerTest(BaseTest): ...@@ -1667,21 +1667,11 @@ class HTTPHandlerTest(BaseTest):
localhost_cert = os.path.join(here, "keycert.pem") localhost_cert = os.path.join(here, "keycert.pem")
sslctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) sslctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
sslctx.load_cert_chain(localhost_cert) sslctx.load_cert_chain(localhost_cert)
# Unfortunately, HTTPHandler doesn't allow us to change the
# SSLContext used by HTTPSConnection, so we have to context = ssl.create_default_context(cafile=localhost_cert)
# monkeypatch. This can be cleaned up if issue 22788 is
# fixed.
old = ssl._create_default_https_context
def restore_handler():
ssl._create_default_https_context = old
self.addCleanup(restore_handler)
def hack_create_ctx():
ctx = old()
ctx.load_verify_locations(localhost_cert)
return ctx
ssl._create_default_https_context = hack_create_ctx
else: else:
sslctx = None sslctx = None
context = None
self.server = server = TestHTTPServer(addr, self.handle_request, self.server = server = TestHTTPServer(addr, self.handle_request,
0.01, sslctx=sslctx) 0.01, sslctx=sslctx)
server.start() server.start()
...@@ -1689,7 +1679,8 @@ class HTTPHandlerTest(BaseTest): ...@@ -1689,7 +1679,8 @@ class HTTPHandlerTest(BaseTest):
host = 'localhost:%d' % server.server_port host = 'localhost:%d' % server.server_port
secure_client = secure and sslctx secure_client = secure and sslctx
self.h_hdlr = logging.handlers.HTTPHandler(host, '/frob', self.h_hdlr = logging.handlers.HTTPHandler(host, '/frob',
secure=secure_client) secure=secure_client,
context=context)
self.log_data = None self.log_data = None
root_logger.addHandler(self.h_hdlr) root_logger.addHandler(self.h_hdlr)
......
...@@ -36,6 +36,8 @@ Core and Builtins ...@@ -36,6 +36,8 @@ Core and Builtins
Library Library
------- -------
- Issue #22788: Add *context* parameter to logging.handlers.HTTPHandler.
- Issue #22921: Allow SSLContext to take the *hostname* parameter even if - Issue #22921: Allow SSLContext to take the *hostname* parameter even if
OpenSSL doesn't support SNI. OpenSSL doesn't support SNI.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment