如何从请求中覆盖 urllib3 中的 respect_retry_after_header?

How override respect_retry_after_header in urllib3 from requests?

当请求此 URL http://www.trouverlesmots.com 时,此 header 被返回:

{'headers': HTTPHeaderDict({'Date': 'Wed, 20 Nov 2019 18:40:39 GMT', 'Server': 'Apache/2.4.41 (Unix)', 'X-Powered-By': 'PHP/7.1.33', 'Expires': 'Wed, 11 Jan 1984 05:00:00 GMT', 'Cache-Control': 'no-cache, must-revalidate, max-age=0', 'Retry-After': '86400', 'Vary': 'User-Agent', 'Connection': 'close', 'Transfer-Encoding': 'chunked', 'Content-Type': 'text/html; charset=UTF-8'}), 'status': 503, 'version': 11, 'reason': 'Service Temporarily Unavailable', 'strict': 0, 'decode_content': False, 'retries': Retry(total=2, connect=None, read=None, redirect=None, status=None), 'enforce_content_length': False, 'auto_close': True, '_decoder': None, '_body': None, '_fp': <http.client.HTTPResponse object at 0x7f2588117940>, '_original_response': <http.client.HTTPResponse object at 0x7f2588117940>, '_fp_bytes_read': 7482, 'msg': None, '_request_url': None, '_pool': <urllib3.connectionpool.HTTPConnectionPool object at 0x7f2588117e10>, '_connection': None, 'chunked': True, 'chunk_left': None, 'length_remaining': None}

隐含两个参数:

retry_after 设置为 86400 所以我的 requests.Session() 暂停了一整天。

这是提交的代码片段:

    def sleep_for_retry(self, response=None):
        retry_after = self.get_retry_after(response)
        if retry_after:
            time.sleep(retry_after)  # stops here
            return True

        return False

来自 urllib3.util.retry.py:277.

Retry 对象的 __init__ 中,

respect_retry_after_header 可能会更改为不遵守 retry_after 参数。

    def __init__(
        self,
        total=10,
        connect=None,
        read=None,
        redirect=None,
        status=None,
        method_whitelist=DEFAULT_METHOD_WHITELIST,
        status_forcelist=None,
        backoff_factor=0,
        raise_on_redirect=True,
        raise_on_status=True,
        history=None,
        respect_retry_after_header=True,
        remove_headers_on_redirect=DEFAULT_REDIRECT_HEADERS_BLACKLIST,
    )

来自 urllib3.util.retry.py:174.

你知道如何从我的 requests.Session() 覆盖 respect_retry_after 参数吗?

由于 sleep_for_retry 调用 get_retry_after,后者调用 parse_retry_after 来解析 Retry-After header 值,您可以使用 parse_retry_after 覆盖 parse_retry_aftermin 函数限制其 return 值的包装函数(下面的示例将其限制在 10 秒):

from urllib3.util.retry import Retry
orig_parse_retry_after = Retry.parse_retry_after
Retry.parse_retry_after = lambda self, retry_after: min(10, orig_parse_retry_after(self, retry_after))

虽然 ,但记录的控制重试的方法是将 urllib3 Retry 对象传递给请求 HTTPAdapter 并将该适配器安装在 Session 对象上。它是这样工作的:

import urllib3
import requests
import requests.adapters

retry = urllib3.Retry(respect_retry_after_header=False)
adapter = requests.adapters.HTTPAdapter(max_retries=retry)
session = requests.Session()
session.mount("http://", adapter)
r = session.get("http://www.trouverlesmots.com")
print(r.status_code, r.headers)