mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-29 18:31:38 +00:00
Upgrade to googleapiclient 1.5.1
This commit is contained in:
@@ -20,6 +20,7 @@ actuall HTTP request.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
import six
|
||||
from six.moves import http_client
|
||||
from six.moves import range
|
||||
|
||||
__author__ = 'jcgregorio@google.com (Joe Gregorio)'
|
||||
@@ -36,11 +37,19 @@ import logging
|
||||
import mimetypes
|
||||
import os
|
||||
import random
|
||||
import ssl
|
||||
import socket
|
||||
import sys
|
||||
import time
|
||||
import uuid
|
||||
|
||||
# TODO(issue 221): Remove this conditional import jibbajabba.
|
||||
try:
|
||||
import ssl
|
||||
except ImportError:
|
||||
_ssl_SSLError = object()
|
||||
else:
|
||||
_ssl_SSLError = ssl.SSLError
|
||||
|
||||
from email.generator import Generator
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.nonmultipart import MIMENonMultipart
|
||||
@@ -57,10 +66,57 @@ from googleapiclient.model import JsonModel
|
||||
from oauth2client import util
|
||||
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_CHUNK_SIZE = 512*1024
|
||||
|
||||
MAX_URI_LENGTH = 2048
|
||||
|
||||
_TOO_MANY_REQUESTS = 429
|
||||
|
||||
|
||||
def _should_retry_response(resp_status, content):
|
||||
"""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.
|
||||
"""
|
||||
# Retry on 5xx errors.
|
||||
if resp_status >= 500:
|
||||
return True
|
||||
|
||||
# Retry on 429 errors.
|
||||
if resp_status == _TOO_MANY_REQUESTS:
|
||||
return True
|
||||
|
||||
# For 403 errors, we have to check for the `reason` in the response to
|
||||
# determine if we should retry.
|
||||
if resp_status == six.moves.http_client.FORBIDDEN:
|
||||
# If there's no details about the 403 type, don't retry.
|
||||
if not content:
|
||||
return False
|
||||
|
||||
# Content is in JSON format.
|
||||
try:
|
||||
data = json.loads(content.decode('utf-8'))
|
||||
reason = data['error']['errors'][0]['reason']
|
||||
except (UnicodeDecodeError, ValueError, KeyError):
|
||||
LOGGER.warning('Invalid JSON content from response: %s', content)
|
||||
return False
|
||||
|
||||
LOGGER.warning('Encountered 403 Forbidden with reason "%s"', reason)
|
||||
|
||||
# Only retry on rate limit related failures.
|
||||
if reason in ('userRateLimitExceeded', 'rateLimitExceeded', ):
|
||||
return True
|
||||
|
||||
# Everything else is a success or non-retriable so break.
|
||||
return False
|
||||
|
||||
|
||||
def _retry_request(http, num_retries, req_type, sleep, rand, uri, method, *args,
|
||||
**kwargs):
|
||||
@@ -82,21 +138,37 @@ def _retry_request(http, num_retries, req_type, sleep, rand, uri, method, *args,
|
||||
resp, content - Response from the http request (may be HTTP 5xx).
|
||||
"""
|
||||
resp = None
|
||||
content = None
|
||||
for retry_num in range(num_retries + 1):
|
||||
if retry_num > 0:
|
||||
sleep(rand() * 2**retry_num)
|
||||
logging.warning(
|
||||
'Retry #%d for %s: %s %s%s' % (retry_num, req_type, method, uri,
|
||||
', following status: %d' % resp.status if resp else ''))
|
||||
# Sleep before retrying.
|
||||
sleep_time = rand() * 2 ** retry_num
|
||||
LOGGER.warning(
|
||||
'Sleeping %.2f seconds before retry %d of %d for %s: %s %s, after %s',
|
||||
sleep_time, retry_num, num_retries, req_type, method, uri,
|
||||
resp.status if resp else exception)
|
||||
sleep(sleep_time)
|
||||
|
||||
try:
|
||||
exception = None
|
||||
resp, content = http.request(uri, method, *args, **kwargs)
|
||||
except ssl.SSLError:
|
||||
if retry_num == num_retries:
|
||||
# Retry on SSL errors and socket timeout errors.
|
||||
except _ssl_SSLError as ssl_error:
|
||||
exception = ssl_error
|
||||
except socket.error as socket_error:
|
||||
# errno's contents differ by platform, so we have to match by name.
|
||||
if socket.errno.errorcode.get(socket_error.errno) not in (
|
||||
'WSAETIMEDOUT', 'ETIMEDOUT', 'EPIPE', 'ECONNABORTED', ):
|
||||
raise
|
||||
exception = socket_error
|
||||
|
||||
if exception:
|
||||
if retry_num == num_retries:
|
||||
raise exception
|
||||
else:
|
||||
continue
|
||||
if resp.status < 500:
|
||||
|
||||
if not _should_retry_response(resp.status, content):
|
||||
break
|
||||
|
||||
return resp, content
|
||||
@@ -882,7 +954,7 @@ class HttpRequest(object):
|
||||
for retry_num in range(num_retries + 1):
|
||||
if retry_num > 0:
|
||||
self._sleep(self._rand() * 2**retry_num)
|
||||
logging.warning(
|
||||
LOGGER.warning(
|
||||
'Retry #%d for media upload: %s %s, following status: %d'
|
||||
% (retry_num, self.method, self.uri, resp.status))
|
||||
|
||||
@@ -1632,7 +1704,7 @@ def tunnel_patch(http):
|
||||
headers = {}
|
||||
if method == 'PATCH':
|
||||
if 'oauth_token' in headers.get('authorization', ''):
|
||||
logging.warning(
|
||||
LOGGER.warning(
|
||||
'OAuth 1.0 request made with Credentials after tunnel_patch.')
|
||||
headers['x-http-method-override'] = "PATCH"
|
||||
method = 'POST'
|
||||
|
||||
Reference in New Issue
Block a user