|
1 |
| -# pylint: disable=protected-access,too-few-public-methods |
| 1 | +# pylint: disable=protected-access,too-few-public-methods,invalid-name,attribute-defined-outside-init |
2 | 2 |
|
3 | 3 | import sys
|
4 | 4 | import urllib.parse
|
5 | 5 |
|
6 | 6 | from base64 import b64encode
|
| 7 | +from datetime import datetime, timedelta |
7 | 8 | from http import HTTPStatus
|
8 | 9 | from http.client import HTTPSConnection
|
9 | 10 | from xmlrpc.client import _Method, SafeTransport, Transport, ServerProxy
|
|
23 | 24 |
|
24 | 25 |
|
25 | 26 | class TCMSProxy(ServerProxy):
|
| 27 | + _connected_since = datetime(2024, 1, 1, 0, 0) |
| 28 | + |
26 | 29 | def __request(self, methodname, params):
|
| 30 | + # refresh the connection every 4 minutes to avoid an |
| 31 | + # `ssl.SSLEOFError: EOF occurred in violation of protocol` error with Python >= 3.10 |
| 32 | + # In practice I've discovered that 5 minutes works as well, 6 minutes fails so |
| 33 | + # be more cautious and refresh the connection earlier! |
| 34 | + # |
| 35 | + # Side note: originally I thought this is related to calling |
| 36 | + # context.set_alpn_protocols(['http/1.1']) inside http/client.py, introduced in |
| 37 | + # https://github.com/python/cpython/commit/f97406be4c0a02c1501c7ab8bc8ef3850eddb962 |
| 38 | + # but that doesn't seem to be the case (or is much harder for me to debug)! |
| 39 | + if getattr( |
| 40 | + self._ServerProxy__transport, # pylint: disable=access-member-before-definition |
| 41 | + "internal_refresh", |
| 42 | + False, |
| 43 | + ) and datetime.now() - self._connected_since > timedelta(minutes=4): |
| 44 | + self._ServerProxy__transport = self._ServerProxy__transport.__class__() |
| 45 | + self._connected_since = datetime.now() |
| 46 | + |
27 | 47 | self._ServerProxy__transport._extra_headers = [("Referer", methodname)]
|
28 | 48 | return self._ServerProxy__request(methodname, params)
|
29 | 49 |
|
@@ -56,12 +76,15 @@ def parse_response(self, response):
|
56 | 76 | class SafeCookieTransport(SafeTransport, CookieTransport):
|
57 | 77 | """SafeTransport subclass that supports cookies."""
|
58 | 78 |
|
| 79 | + internal_refresh = True |
59 | 80 | scheme = "https"
|
60 | 81 |
|
61 | 82 |
|
62 | 83 | class KerbTransport(SafeCookieTransport):
|
63 | 84 | """Handles GSSAPI Negotiation (SPNEGO) authentication."""
|
64 | 85 |
|
| 86 | + internal_refresh = False |
| 87 | + |
65 | 88 | def get_host_info(self, host):
|
66 | 89 | host, extra_headers, x509 = Transport.get_host_info(self, host)
|
67 | 90 |
|
|
0 commit comments