|
5 | 5 | import os |
6 | 6 | import socket |
7 | 7 | from socketserver import ThreadingMixIn |
| 8 | +import ssl |
8 | 9 | import sys |
9 | 10 | import threading |
10 | | -from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple |
| 11 | +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union |
11 | 12 | from urllib.error import HTTPError |
12 | 13 | from urllib.parse import parse_qs, quote_plus, urlparse |
13 | 14 | from urllib.request import ( |
14 | | - build_opener, HTTPHandler, HTTPRedirectHandler, Request, |
| 15 | + BaseHandler, build_opener, HTTPHandler, HTTPRedirectHandler, HTTPSHandler, |
| 16 | + Request, |
15 | 17 | ) |
16 | | -import warnings |
17 | 18 | from wsgiref.simple_server import make_server, WSGIRequestHandler, WSGIServer |
18 | 19 |
|
19 | 20 | from .openmetrics import exposition as openmetrics |
@@ -247,15 +248,6 @@ def choose_encoder(accept_header: str) -> Tuple[Callable[[CollectorRegistry], by |
247 | 248 | return generate_latest, CONTENT_TYPE_LATEST |
248 | 249 |
|
249 | 250 |
|
250 | | -def choose_formatter(accept_header: str) -> Tuple[Callable[[CollectorRegistry], bytes], str]: |
251 | | - warnings.warn( |
252 | | - "choose_formatter is deprecated and will be removed in 0.15.0, please use choose_encoder instead", |
253 | | - DeprecationWarning, |
254 | | - stacklevel=2 |
255 | | - ) |
256 | | - return choose_encoder(accept_header) |
257 | | - |
258 | | - |
259 | 251 | def gzip_accepted(accept_encoding_header: str) -> bool: |
260 | 252 | accept_encoding_header = accept_encoding_header or '' |
261 | 253 | for accepted in accept_encoding_header.split(','): |
@@ -324,7 +316,7 @@ def _make_handler( |
324 | 316 | timeout: Optional[float], |
325 | 317 | headers: Sequence[Tuple[str, str]], |
326 | 318 | data: bytes, |
327 | | - base_handler: type, |
| 319 | + base_handler: Union[BaseHandler, type], |
328 | 320 | ) -> Callable[[], None]: |
329 | 321 | def handle() -> None: |
330 | 322 | request = Request(url, data=data) |
@@ -399,6 +391,40 @@ def handle(): |
399 | 391 | return handle |
400 | 392 |
|
401 | 393 |
|
| 394 | +def tls_auth_handler( |
| 395 | + url: str, |
| 396 | + method: str, |
| 397 | + timeout: Optional[float], |
| 398 | + headers: List[Tuple[str, str]], |
| 399 | + data: bytes, |
| 400 | + certfile: str, |
| 401 | + keyfile: str, |
| 402 | + cafile: Optional[str] = None, |
| 403 | + protocol: int = ssl.PROTOCOL_TLS_CLIENT, |
| 404 | + insecure_skip_verify: bool = False, |
| 405 | +) -> Callable[[], None]: |
| 406 | + """Handler that implements an HTTPS connection with TLS Auth. |
| 407 | +
|
| 408 | + The default protocol (ssl.PROTOCOL_TLS_CLIENT) will also enable |
| 409 | + ssl.CERT_REQUIRED and SSLContext.check_hostname by default. This can be |
| 410 | + disabled by setting insecure_skip_verify to True. |
| 411 | + |
| 412 | + Both this handler and the TLS feature on pushgateay are experimental.""" |
| 413 | + context = ssl.SSLContext(protocol=protocol) |
| 414 | + if cafile is not None: |
| 415 | + context.load_verify_locations(cafile) |
| 416 | + else: |
| 417 | + context.load_default_certs() |
| 418 | + |
| 419 | + if insecure_skip_verify: |
| 420 | + context.check_hostname = False |
| 421 | + context.verify_mode = ssl.CERT_NONE |
| 422 | + |
| 423 | + context.load_cert_chain(certfile=certfile, keyfile=keyfile) |
| 424 | + handler = HTTPSHandler(context=context) |
| 425 | + return _make_handler(url, method, timeout, headers, data, handler) |
| 426 | + |
| 427 | + |
402 | 428 | def push_to_gateway( |
403 | 429 | gateway: str, |
404 | 430 | job: str, |
|
0 commit comments