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



请求此 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}

隐含两个参数:

  • status_code: 503这意味着一个retries过程
  • retry_after: 86400

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.

respect_retry_after_header可以更改为不遵守retry_after参数,以Retry对象的__init__

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参数吗?

虽然这个答案可能有效,但记录的控制重试的方法是将 urllib3Retry对象传递给请求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)

由于sleep_for_retry调用get_retry_after,它调用parse_retry_after来解析Retry-After标头值,因此您可以使用包装函数覆盖parse_retry_after,该包装函数使用min函数限制其返回值(下面的示例将其上限为 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))

最新更新