Determines whether a response should be retried. Args: resp_status: The response status received. content: The response content body. Returns: True if the response should be retried, otherwise False.
(resp_status, content)
| 78 | |
| 79 | |
| 80 | def _should_retry_response(resp_status, content): |
| 81 | """Determines whether a response should be retried. |
| 82 | |
| 83 | Args: |
| 84 | resp_status: The response status received. |
| 85 | content: The response content body. |
| 86 | |
| 87 | Returns: |
| 88 | True if the response should be retried, otherwise False. |
| 89 | """ |
| 90 | reason = None |
| 91 | |
| 92 | # Retry on 5xx errors. |
| 93 | if resp_status >= 500: |
| 94 | return True |
| 95 | |
| 96 | # Retry on 429 errors. |
| 97 | if resp_status == _TOO_MANY_REQUESTS: |
| 98 | return True |
| 99 | |
| 100 | # For 403 errors, we have to check for the `reason` in the response to |
| 101 | # determine if we should retry. |
| 102 | if resp_status == http_client.FORBIDDEN: |
| 103 | # If there's no details about the 403 type, don't retry. |
| 104 | if not content: |
| 105 | return False |
| 106 | |
| 107 | # Content is in JSON format. |
| 108 | try: |
| 109 | data = json.loads(content.decode("utf-8")) |
| 110 | if isinstance(data, dict): |
| 111 | # There are many variations of the error json so we need |
| 112 | # to determine the keyword which has the error detail. Make sure |
| 113 | # that the order of the keywords below isn't changed as it can |
| 114 | # break user code. If the "errors" key exists, we must use that |
| 115 | # first. |
| 116 | # See Issue #1243 |
| 117 | # https://github.com/googleapis/google-api-python-client/issues/1243 |
| 118 | error_detail_keyword = next( |
| 119 | ( |
| 120 | kw |
| 121 | for kw in ["errors", "status", "message"] |
| 122 | if kw in data["error"] |
| 123 | ), |
| 124 | "", |
| 125 | ) |
| 126 | |
| 127 | if error_detail_keyword: |
| 128 | reason = data["error"][error_detail_keyword] |
| 129 | |
| 130 | if isinstance(reason, list) and len(reason) > 0: |
| 131 | reason = reason[0] |
| 132 | if "reason" in reason: |
| 133 | reason = reason["reason"] |
| 134 | else: |
| 135 | reason = data[0]["error"]["errors"]["reason"] |
| 136 | except (UnicodeDecodeError, ValueError, KeyError): |
| 137 | LOGGER.warning("Invalid JSON content from response: %s", content) |
no outgoing calls
no test coverage detected
searching dependent graphs…