# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Classes to encapsulate a single HTTP request.

The classes implement a command pattern, with every
object supporting an execute() method that does the
actual 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)"

from six import BytesIO, StringIO
from six.moves.urllib.parse import urlparse, urlunparse, quote, unquote

import copy
import httplib2
import json
import logging
import mimetypes
import os
import random
import socket
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
from email.parser import FeedParser

from googleapiclient import _helpers as util

from googleapiclient import _auth
from googleapiclient.errors import BatchError
from googleapiclient.errors import HttpError
from googleapiclient.errors import InvalidChunkSizeError
from googleapiclient.errors import ResumableUploadError
from googleapiclient.errors import UnexpectedBodyError
from googleapiclient.errors import UnexpectedMethodError
from googleapiclient.model import JsonModel


LOGGER = logging.getLogger(__name__)

DEFAULT_CHUNK_SIZE = 100 * 1024 * 1024

MAX_URI_LENGTH = 2048

MAX_BATCH_LIMIT = 1000

_TOO_MANY_REQUESTS = 429

DEFAULT_HTTP_TIMEOUT_SEC = 60

_LEGACY_BATCH_URI = "https://www.googleapis.com/batch"

if six.PY2:
    # That's a builtin python3 exception, nonexistent in python2.
    # Defined to None to avoid NameError while trying to catch it
    ConnectionError = None


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.
  """
    reason = None

    # 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"))
            if isinstance(data, dict):
                # There are many variations of the error json so we need
                # to determine the keyword which has the error detail. Make sure
                # that the order of the keywords below isn't changed as it can
                # break user code. If the "errors" key exists, we must use that
                # first.
                # See Issue #1243
                # https://github.com/googleapis/google-api-python-client/issues/1243
                error_detail_keyword = next((kw for kw in ["errors", "status", "message"] if kw in data["error"]), "")

                if error_detail_keyword:
                    reason = data["error"][error_detail_keyword]

                    if isinstance(reason, list) and len(reason) > 0:
                        reason = reason[0]
                        if "reason" in reason:
                            reason = reason["reason"]
            else:
                reason = data[0]["error"]["errors"]["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
):
    """Retries an HTTP request multiple times while handling errors.

  If after all retries the request still fails, last error is either returned as
  return value (for HTTP 5xx errors) or thrown (for ssl.SSLError).

  Args:
    http: Http object to be used to execute request.
    num_retries: Maximum number of retries.
    req_type: Type of the request (used for logging retries).
    sleep, rand: Functions to sleep for random time between retries.
    uri: URI to be requested.
    method: HTTP method to be used.
    args, kwargs: Additional arguments passed to http.request.

  Returns:
    resp, content - Response from the http request (may be HTTP 5xx).
  """
    resp = None
    content = None
    exception = None
    for retry_num in range(num_retries + 1):
        if retry_num > 0:
            # 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)
        # Retry on SSL errors and socket timeout errors.
        except _ssl_SSLError as ssl_error:
            exception = ssl_error
        except socket.timeout as socket_timeout:
            # Needs to be before socket.error as it's a subclass of OSError
            # socket.timeout has no errorcode
            exception = socket_timeout
        except ConnectionError as connection_error:
            # Needs to be before socket.error as it's a subclass of OSError
            exception = connection_error
        except OSError as socket_error:
            # errno's contents differ by platform, so we have to match by name.
            # Some of these same errors may have been caught above, e.g. ECONNRESET *should* be
            # raised as a ConnectionError, but some libraries will raise it as a socket.error
            # with an errno corresponding to ECONNRESET
            if socket.errno.errorcode.get(socket_error.errno) not in {
                "WSAETIMEDOUT",
                "ETIMEDOUT",
                "EPIPE",
                "ECONNABORTED",
                "ECONNREFUSED",
                "ECONNRESET",
            }:
                raise
            exception = socket_error
        except httplib2.ServerNotFoundError as server_not_found_error:
            exception = server_not_found_error

        if exception:
            if retry_num == num_retries:
                raise exception
            else:
                continue

        if not _should_retry_response(resp.status, content):
            break

    return resp, content


class MediaUploadProgress(object):
    """Status of a resumable upload."""

    def __init__(self, resumable_progress, total_size):
        """Constructor.

    Args:
      resumable_progress: int, bytes sent so far.
      total_size: int, total bytes in complete upload, or None if the total
        upload size isn't known ahead of time.
    """
        self.resumable_progress = resumable_progress
        self.total_size = total_size

    def progress(self):
        """Percent of upload completed, as a float.

    Returns:
      the percentage complete as a float, returning 0.0 if the total size of
      the upload is unknown.
    """
        if self.total_size is not None and self.total_size != 0:
            return float(self.resumable_progress) / float(self.total_size)
        else:
            return 0.0


class MediaDownloadProgress(object):
    """Status of a resumable download."""

    def __init__(self, resumable_progress, total_size):
        """Constructor.

    Args:
      resumable_progress: int, bytes received so far.
      total_size: int, total bytes in complete download.
    """
        self.resumable_progress = resumable_progress
        self.total_size = total_size

    def progress(self):
        """Percent of download completed, as a float.

    Returns:
      the percentage complete as a float, returning 0.0 if the total size of
      the download is unknown.
    """
        if self.total_size is not None and self.total_size != 0:
            return float(self.resumable_progress) / float(self.total_size)
        else:
            return 0.0


class MediaUpload(object):
    """Describes a media object to upload.

  Base class that defines the interface of MediaUpload subclasses.

  Note that subclasses of MediaUpload may allow you to control the chunksize
  when uploading a media object. It is important to keep the size of the chunk
  as large as possible to keep the upload efficient. Other factors may influence
  the size of the chunk you use, particularly if you are working in an
  environment where individual HTTP requests may have a hardcoded time limit,
  such as under certain classes of requests under Google App Engine.

  Streams are io.Base compatible objects that support seek(). Some MediaUpload
  subclasses support using streams directly to upload data. Support for
  streaming may be indicated by a MediaUpload sub-class and if appropriate for a
  platform that stream will be used for uploading the media object. The support
  for streaming is indicated by has_stream() returning True. The stream() method
  should return an io.Base object that supports seek(). On platforms where the
  underlying httplib module supports streaming, for example Python 2.6 and
  later, the stream will be passed into the http library which will result in
  less memory being used and possibly faster uploads.

  If you need to upload media that can't be uploaded using any of the existing
  MediaUpload sub-class then you can sub-class MediaUpload for your particular
  needs.
  """

    def chunksize(self):
        """Chunk size for resumable uploads.

    Returns:
      Chunk size in bytes.
    """
        raise NotImplementedError()

    def mimetype(self):
        """Mime type of the body.

    Returns:
      Mime type.
    """
        return "application/octet-stream"

    def size(self):
        """Size of upload.

    Returns:
      Size of the body, or None of the size is unknown.
    """
        return None

    def resumable(self):
        """Whether this upload is resumable.

    Returns:
      True if resumable upload or False.
    """
        return False

    def getbytes(self, begin, end):
        """Get bytes from the media.

    Args:
      begin: int, offset from beginning of file.
      length: int, number of bytes to read, starting at begin.

    Returns:
      A string of bytes read. May be shorter than length if EOF was reached
      first.
    """
        raise NotImplementedError()

    def has_stream(self):
        """Does the underlying upload support a streaming interface.

    Streaming means it is an io.IOBase subclass that supports seek, i.e.
    seekable() returns True.

    Returns:
      True if the call to stream() will return an instance of a seekable io.Base
      subclass.
    """
        return False

    def stream(self):
        """A stream interface to the data being uploaded.

    Returns:
      The returned value is an io.IOBase subclass that supports seek, i.e.
      seekable() returns True.
    """
        raise NotImplementedError()

    @util.positional(1)
    def _to_json(self, strip=None):
        """Utility function for creating a JSON representation of a MediaUpload.

    Args:
      strip: array, An array of names of members to not include in the JSON.

    Returns:
       string, a JSON representation of this instance, suitable to pass to
       from_json().
    """
        t = type(self)
        d = copy.copy(self.__dict__)
        if strip is not None:
            for member in strip:
                del d[member]
        d["_class"] = t.__name__
        d["_module"] = t.__module__
        return json.dumps(d)

    def to_json(self):
        """Create a JSON representation of an instance of MediaUpload.

    Returns:
       string, a JSON representation of this instance, suitable to pass to
       from_json().
    """
        return self._to_json()

    @classmethod
    def new_from_json(cls, s):
        """Utility class method to instantiate a MediaUpload subclass from a JSON
    representation produced by to_json().

    Args:
      s: string, JSON from to_json().

    Returns:
      An instance of the subclass of MediaUpload that was serialized with
      to_json().
    """
        data = json.loads(s)
        # Find and call the right classmethod from_json() to restore the object.
        module = data["_module"]
        m = __import__(module, fromlist=module.split(".")[:-1])
        kls = getattr(m, data["_class"])
        from_json = getattr(kls, "from_json")
        return from_json(s)


class MediaIoBaseUpload(MediaUpload):
    """A MediaUpload for a io.Base objects.

  Note that the Python file object is compatible with io.Base and can be used
  with this class also.

    fh = BytesIO('...Some data to upload...')
    media = MediaIoBaseUpload(fh, mimetype='image/png',
      chunksize=1024*1024, resumable=True)
    farm.animals().insert(
        id='cow',
        name='cow.png',
        media_body=media).execute()

  Depending on the platform you are working on, you may pass -1 as the
  chunksize, which indicates that the entire file should be uploaded in a single
  request. If the underlying platform supports streams, such as Python 2.6 or
  later, then this can be very efficient as it avoids multiple connections, and
  also avoids loading the entire file into memory before sending it. Note that
  Google App Engine has a 5MB limit on request size, so you should never set
  your chunksize larger than 5MB, or to -1.
  """

    @util.positional(3)
    def __init__(self, fd, mimetype, chunksize=DEFAULT_CHUNK_SIZE, resumable=False):
        """Constructor.

    Args:
      fd: io.Base or file object, The source of the bytes to upload. MUST be
        opened in blocking mode, do not use streams opened in non-blocking mode.
        The given stream must be seekable, that is, it must be able to call
        seek() on fd.
      mimetype: string, Mime-type of the file.
      chunksize: int, File will be uploaded in chunks of this many bytes. Only
        used if resumable=True. Pass in a value of -1 if the file is to be
        uploaded as a single chunk. Note that Google App Engine has a 5MB limit
        on request size, so you should never set your chunksize larger than 5MB,
        or to -1.
      resumable: bool, True if this is a resumable upload. False means upload
        in a single request.
    """
        super(MediaIoBaseUpload, self).__init__()
        self._fd = fd
        self._mimetype = mimetype
        if not (chunksize == -1 or chunksize > 0):
            raise InvalidChunkSizeError()
        self._chunksize = chunksize
        self._resumable = resumable

        self._fd.seek(0, os.SEEK_END)
        self._size = self._fd.tell()

    def chunksize(self):
        """Chunk size for resumable uploads.

    Returns:
      Chunk size in bytes.
    """
        return self._chunksize

    def mimetype(self):
        """Mime type of the body.

    Returns:
      Mime type.
    """
        return self._mimetype

    def size(self):
        """Size of upload.

    Returns:
      Size of the body, or None of the size is unknown.
    """
        return self._size

    def resumable(self):
        """Whether this upload is resumable.

    Returns:
      True if resumable upload or False.
    """
        return self._resumable

    def getbytes(self, begin, length):
        """Get bytes from the media.

    Args:
      begin: int, offset from beginning of file.
      length: int, number of bytes to read, starting at begin.

    Returns:
      A string of bytes read. May be shorted than length if EOF was reached
      first.
    """
        self._fd.seek(begin)
        return self._fd.read(length)

    def has_stream(self):
        """Does the underlying upload support a streaming interface.

    Streaming means it is an io.IOBase subclass that supports seek, i.e.
    seekable() returns True.

    Returns:
      True if the call to stream() will return an instance of a seekable io.Base
      subclass.
    """
        return True

    def stream(self):
        """A stream interface to the data being uploaded.

    Returns:
      The returned value is an io.IOBase subclass that supports seek, i.e.
      seekable() returns True.
    """
        return self._fd

    def to_json(self):
        """This upload type is not serializable."""
        raise NotImplementedError("MediaIoBaseUpload is not serializable.")


class MediaFileUpload(MediaIoBaseUpload):
    """A MediaUpload for a file.

  Construct a MediaFileUpload and pass as the media_body parameter of the
  method. For example, if we had a service that allowed uploading images:

    media = MediaFileUpload('cow.png', mimetype='image/png',
      chunksize=1024*1024, resumable=True)
    farm.animals().insert(
        id='cow',
        name='cow.png',
        media_body=media).execute()

  Depending on the platform you are working on, you may pass -1 as the
  chunksize, which indicates that the entire file should be uploaded in a single
  request. If the underlying platform supports streams, such as Python 2.6 or
  later, then this can be very efficient as it avoids multiple connections, and
  also avoids loading the entire file into memory before sending it. Note that
  Google App Engine has a 5MB limit on request size, so you should never set
  your chunksize larger than 5MB, or to -1.
  """

    @util.positional(2)
    def __init__(
        self, filename, mimetype=None, chunksize=DEFAULT_CHUNK_SIZE, resumable=False
    ):
        """Constructor.

    Args:
      filename: string, Name of the file.
      mimetype: string, Mime-type of the file. If None then a mime-type will be
        guessed from the file extension.
      chunksize: int, File will be uploaded in chunks of this many bytes. Only
        used if resumable=True. Pass in a value of -1 if the file is to be
        uploaded in a single chunk. Note that Google App Engine has a 5MB limit
        on request size, so you should never set your chunksize larger than 5MB,
        or to -1.
      resumable: bool, True if this is a resumable upload. False means upload
        in a single request.
    """
        self._fd = None
        self._filename = filename
        self._fd = open(self._filename, "rb")
        if mimetype is None:
            # No mimetype provided, make a guess.
            mimetype, _ = mimetypes.guess_type(filename)
            if mimetype is None:
                # Guess failed, use octet-stream.
                mimetype = "application/octet-stream"
        super(MediaFileUpload, self).__init__(
            self._fd, mimetype, chunksize=chunksize, resumable=resumable
        )

    def __del__(self):
        if self._fd:
            self._fd.close()

    def to_json(self):
        """Creating a JSON representation of an instance of MediaFileUpload.

    Returns:
       string, a JSON representation of this instance, suitable to pass to
       from_json().
    """
        return self._to_json(strip=["_fd"])

    @staticmethod
    def from_json(s):
        d = json.loads(s)
        return MediaFileUpload(
            d["_filename"],
            mimetype=d["_mimetype"],
            chunksize=d["_chunksize"],
            resumable=d["_resumable"],
        )


class MediaInMemoryUpload(MediaIoBaseUpload):
    """MediaUpload for a chunk of bytes.

  DEPRECATED: Use MediaIoBaseUpload with either io.TextIOBase or StringIO for
  the stream.
  """

    @util.positional(2)
    def __init__(
        self,
        body,
        mimetype="application/octet-stream",
        chunksize=DEFAULT_CHUNK_SIZE,
        resumable=False,
    ):
        """Create a new MediaInMemoryUpload.

  DEPRECATED: Use MediaIoBaseUpload with either io.TextIOBase or StringIO for
  the stream.

  Args:
    body: string, Bytes of body content.
    mimetype: string, Mime-type of the file or default of
      'application/octet-stream'.
    chunksize: int, File will be uploaded in chunks of this many bytes. Only
      used if resumable=True.
    resumable: bool, True if this is a resumable upload. False means upload
      in a single request.
    """
        fd = BytesIO(body)
        super(MediaInMemoryUpload, self).__init__(
            fd, mimetype, chunksize=chunksize, resumable=resumable
        )


class MediaIoBaseDownload(object):
    """"Download media resources.

  Note that the Python file object is compatible with io.Base and can be used
  with this class also.


  Example:
    request = farms.animals().get_media(id='cow')
    fh = io.FileIO('cow.png', mode='wb')
    downloader = MediaIoBaseDownload(fh, request, chunksize=1024*1024)

    done = False
    while done is False:
      status, done = downloader.next_chunk()
      if status:
        print "Download %d%%." % int(status.progress() * 100)
    print "Download Complete!"
  """

    @util.positional(3)
    def __init__(self, fd, request, chunksize=DEFAULT_CHUNK_SIZE):
        """Constructor.

    Args:
      fd: io.Base or file object, The stream in which to write the downloaded
        bytes.
      request: googleapiclient.http.HttpRequest, the media request to perform in
        chunks.
      chunksize: int, File will be downloaded in chunks of this many bytes.
    """
        self._fd = fd
        self._request = request
        self._uri = request.uri
        self._chunksize = chunksize
        self._progress = 0
        self._total_size = None
        self._done = False

        # Stubs for testing.
        self._sleep = time.sleep
        self._rand = random.random

        self._headers = {}
        for k, v in six.iteritems(request.headers):
            # allow users to supply custom headers by setting them on the request
            # but strip out the ones that are set by default on requests generated by
            # API methods like Drive's files().get(fileId=...)
            if not k.lower() in ("accept", "accept-encoding", "user-agent"):
                self._headers[k] = v

    @util.positional(1)
    def next_chunk(self, num_retries=0):
        """Get the next chunk of the download.

    Args:
      num_retries: Integer, number of times to retry with randomized
            exponential backoff. If all retries fail, the raised HttpError
            represents the last request. If zero (default), we attempt the
            request only once.

    Returns:
      (status, done): (MediaDownloadProgress, boolean)
         The value of 'done' will be True when the media has been fully
         downloaded or the total size of the media is unknown.

    Raises:
      googleapiclient.errors.HttpError if the response was not a 2xx.
      httplib2.HttpLib2Error if a transport error has occurred.
    """
        headers = self._headers.copy()
        headers["range"] = "bytes=%d-%d" % (
            self._progress,
            self._progress + self._chunksize,
        )
        http = self._request.http

        resp, content = _retry_request(
            http,
            num_retries,
            "media download",
            self._sleep,
            self._rand,
            self._uri,
            "GET",
            headers=headers,
        )

        if resp.status in [200, 206]:
            if "content-location" in resp and resp["content-location"] != self._uri:
                self._uri = resp["content-location"]
            self._progress += len(content)
            self._fd.write(content)

            if "content-range" in resp:
                content_range = resp["content-range"]
                length = content_range.rsplit("/", 1)[1]
                self._total_size = int(length)
            elif "content-length" in resp:
                self._total_size = int(resp["content-length"])

            if self._total_size is None or self._progress == self._total_size:
                self._done = True
            return MediaDownloadProgress(self._progress, self._total_size), self._done
        elif resp.status == 416:
            # 416 is Range Not Satisfiable
            # This typically occurs with a zero byte file
            content_range = resp["content-range"]
            length = content_range.rsplit("/", 1)[1]
            self._total_size = int(length)
            if self._total_size == 0:
                self._done = True
                return MediaDownloadProgress(self._progress, self._total_size), self._done
        raise HttpError(resp, content, uri=self._uri)


class _StreamSlice(object):
    """Truncated stream.

  Takes a stream and presents a stream that is a slice of the original stream.
  This is used when uploading media in chunks. In later versions of Python a
  stream can be passed to httplib in place of the string of data to send. The
  problem is that httplib just blindly reads to the end of the stream. This
  wrapper presents a virtual stream that only reads to the end of the chunk.
  """

    def __init__(self, stream, begin, chunksize):
        """Constructor.

    Args:
      stream: (io.Base, file object), the stream to wrap.
      begin: int, the seek position the chunk begins at.
      chunksize: int, the size of the chunk.
    """
        self._stream = stream
        self._begin = begin
        self._chunksize = chunksize
        self._stream.seek(begin)

    def read(self, n=-1):
        """Read n bytes.

    Args:
      n, int, the number of bytes to read.

    Returns:
      A string of length 'n', or less if EOF is reached.
    """
        # The data left available to read sits in [cur, end)
        cur = self._stream.tell()
        end = self._begin + self._chunksize
        if n == -1 or cur + n > end:
            n = end - cur
        return self._stream.read(n)


class HttpRequest(object):
    """Encapsulates a single HTTP request."""

    @util.positional(4)
    def __init__(
        self,
        http,
        postproc,
        uri,
        method="GET",
        body=None,
        headers=None,
        methodId=None,
        resumable=None,
    ):
        """Constructor for an HttpRequest.

    Args:
      http: httplib2.Http, the transport object to use to make a request
      postproc: callable, called on the HTTP response and content to transform
                it into a data object before returning, or raising an exception
                on an error.
      uri: string, the absolute URI to send the request to
      method: string, the HTTP method to use
      body: string, the request body of the HTTP request,
      headers: dict, the HTTP request headers
      methodId: string, a unique identifier for the API method being called.
      resumable: MediaUpload, None if this is not a resumbale request.
    """
        self.uri = uri
        self.method = method
        self.body = body
        self.headers = headers or {}
        self.methodId = methodId
        self.http = http
        self.postproc = postproc
        self.resumable = resumable
        self.response_callbacks = []
        self._in_error_state = False

        # The size of the non-media part of the request.
        self.body_size = len(self.body or "")

        # The resumable URI to send chunks to.
        self.resumable_uri = None

        # The bytes that have been uploaded.
        self.resumable_progress = 0

        # Stubs for testing.
        self._rand = random.random
        self._sleep = time.sleep

    @util.positional(1)
    def execute(self, http=None, num_retries=0):
        """Execute the request.

    Args:
      http: httplib2.Http, an http object to be used in place of the
            one the HttpRequest request object was constructed with.
      num_retries: Integer, number of times to retry with randomized
            exponential backoff. If all retries fail, the raised HttpError
            represents the last request. If zero (default), we attempt the
            request only once.

    Returns:
      A deserialized object model of the response body as determined
      by the postproc.

    Raises:
      googleapiclient.errors.HttpError if the response was not a 2xx.
      httplib2.HttpLib2Error if a transport error has occurred.
    """
        if http is None:
            http = self.http

        if self.resumable:
            body = None
            while body is None:
                _, body = self.next_chunk(http=http, num_retries=num_retries)
            return body

        # Non-resumable case.

        if "content-length" not in self.headers:
            self.headers["content-length"] = str(self.body_size)
        # If the request URI is too long then turn it into a POST request.
        # Assume that a GET request never contains a request body.
        if len(self.uri) > MAX_URI_LENGTH and self.method == "GET":
            self.method = "POST"
            self.headers["x-http-method-override"] = "GET"
            self.headers["content-type"] = "application/x-www-form-urlencoded"
            parsed = urlparse(self.uri)
            self.uri = urlunparse(
                (parsed.scheme, parsed.netloc, parsed.path, parsed.params, None, None)
            )
            self.body = parsed.query
            self.headers["content-length"] = str(len(self.body))

        # Handle retries for server-side errors.
        resp, content = _retry_request(
            http,
            num_retries,
            "request",
            self._sleep,
            self._rand,
            str(self.uri),
            method=str(self.method),
            body=self.body,
            headers=self.headers,
        )

        for callback in self.response_callbacks:
            callback(resp)
        if resp.status >= 300:
            raise HttpError(resp, content, uri=self.uri)
        return self.postproc(resp, content)

    @util.positional(2)
    def add_response_callback(self, cb):
        """add_response_headers_callback

    Args:
      cb: Callback to be called on receiving the response headers, of signature:

      def cb(resp):
        # Where resp is an instance of httplib2.Response
    """
        self.response_callbacks.append(cb)

    @util.positional(1)
    def next_chunk(self, http=None, num_retries=0):
        """Execute the next step of a resumable upload.

    Can only be used if the method being executed supports media uploads and
    the MediaUpload object passed in was flagged as using resumable upload.

    Example:

      media = MediaFileUpload('cow.png', mimetype='image/png',
                              chunksize=1000, resumable=True)
      request = farm.animals().insert(
          id='cow',
          name='cow.png',
          media_body=media)

      response = None
      while response is None:
        status, response = request.next_chunk()
        if status:
          print "Upload %d%% complete." % int(status.progress() * 100)


    Args:
      http: httplib2.Http, an http object to be used in place of the
            one the HttpRequest request object was constructed with.
      num_retries: Integer, number of times to retry with randomized
            exponential backoff. If all retries fail, the raised HttpError
            represents the last request. If zero (default), we attempt the
            request only once.

    Returns:
      (status, body): (ResumableMediaStatus, object)
         The body will be None until the resumable media is fully uploaded.

    Raises:
      googleapiclient.errors.HttpError if the response was not a 2xx.
      httplib2.HttpLib2Error if a transport error has occurred.
    """
        if http is None:
            http = self.http

        if self.resumable.size() is None:
            size = "*"
        else:
            size = str(self.resumable.size())

        if self.resumable_uri is None:
            start_headers = copy.copy(self.headers)
            start_headers["X-Upload-Content-Type"] = self.resumable.mimetype()
            if size != "*":
                start_headers["X-Upload-Content-Length"] = size
            start_headers["content-length"] = str(self.body_size)

            resp, content = _retry_request(
                http,
                num_retries,
                "resumable URI request",
                self._sleep,
                self._rand,
                self.uri,
                method=self.method,
                body=self.body,
                headers=start_headers,
            )

            if resp.status == 200 and "location" in resp:
                self.resumable_uri = resp["location"]
            else:
                raise ResumableUploadError(resp, content)
        elif self._in_error_state:
            # If we are in an error state then query the server for current state of
            # the upload by sending an empty PUT and reading the 'range' header in
            # the response.
            headers = {"Content-Range": "bytes */%s" % size, "content-length": "0"}
            resp, content = http.request(self.resumable_uri, "PUT", headers=headers)
            status, body = self._process_response(resp, content)
            if body:
                # The upload was complete.
                return (status, body)

        if self.resumable.has_stream():
            data = self.resumable.stream()
            if self.resumable.chunksize() == -1:
                data.seek(self.resumable_progress)
                chunk_end = self.resumable.size() - self.resumable_progress - 1
            else:
                # Doing chunking with a stream, so wrap a slice of the stream.
                data = _StreamSlice(
                    data, self.resumable_progress, self.resumable.chunksize()
                )
                chunk_end = min(
                    self.resumable_progress + self.resumable.chunksize() - 1,
                    self.resumable.size() - 1,
                )
        else:
            data = self.resumable.getbytes(
                self.resumable_progress, self.resumable.chunksize()
            )

            # A short read implies that we are at EOF, so finish the upload.
            if len(data) < self.resumable.chunksize():
                size = str(self.resumable_progress + len(data))

            chunk_end = self.resumable_progress + len(data) - 1

        headers = {
            # Must set the content-length header here because httplib can't
            # calculate the size when working with _StreamSlice.
            "Content-Length": str(chunk_end - self.resumable_progress + 1),
        }

        # An empty file results in chunk_end = -1 and size = 0
        # sending "bytes 0--1/0" results in an invalid request
        # Only add header "Content-Range" if chunk_end != -1
        if chunk_end != -1:
            headers["Content-Range"] = "bytes %d-%d/%s" % (self.resumable_progress, chunk_end, size)

        for retry_num in range(num_retries + 1):
            if retry_num > 0:
                self._sleep(self._rand() * 2 ** retry_num)
                LOGGER.warning(
                    "Retry #%d for media upload: %s %s, following status: %d"
                    % (retry_num, self.method, self.uri, resp.status)
                )

            try:
                resp, content = http.request(
                    self.resumable_uri, method="PUT", body=data, headers=headers
                )
            except:
                self._in_error_state = True
                raise
            if not _should_retry_response(resp.status, content):
                break

        return self._process_response(resp, content)

    def _process_response(self, resp, content):
        """Process the response from a single chunk upload.

    Args:
      resp: httplib2.Response, the response object.
      content: string, the content of the response.

    Returns:
      (status, body): (ResumableMediaStatus, object)
         The body will be None until the resumable media is fully uploaded.

    Raises:
      googleapiclient.errors.HttpError if the response was not a 2xx or a 308.
    """
        if resp.status in [200, 201]:
            self._in_error_state = False
            return None, self.postproc(resp, content)
        elif resp.status == 308:
            self._in_error_state = False
            # A "308 Resume Incomplete" indicates we are not done.
            try:
                self.resumable_progress = int(resp["range"].split("-")[1]) + 1
            except KeyError:
                # If resp doesn't contain range header, resumable progress is 0
                self.resumable_progress = 0
            if "location" in resp:
                self.resumable_uri = resp["location"]
        else:
            self._in_error_state = True
            raise HttpError(resp, content, uri=self.uri)

        return (
            MediaUploadProgress(self.resumable_progress, self.resumable.size()),
            None,
        )

    def to_json(self):
        """Returns a JSON representation of the HttpRequest."""
        d = copy.copy(self.__dict__)
        if d["resumable"] is not None:
            d["resumable"] = self.resumable.to_json()
        del d["http"]
        del d["postproc"]
        del d["_sleep"]
        del d["_rand"]

        return json.dumps(d)

    @staticmethod
    def from_json(s, http, postproc):
        """Returns an HttpRequest populated with info from a JSON object."""
        d = json.loads(s)
        if d["resumable"] is not None:
            d["resumable"] = MediaUpload.new_from_json(d["resumable"])
        return HttpRequest(
            http,
            postproc,
            uri=d["uri"],
            method=d["method"],
            body=d["body"],
            headers=d["headers"],
            methodId=d["methodId"],
            resumable=d["resumable"],
        )

    @staticmethod
    def null_postproc(resp, contents):
        return resp, contents


class BatchHttpRequest(object):
    """Batches multiple HttpRequest objects into a single HTTP request.

  Example:
    from googleapiclient.http import BatchHttpRequest

    def list_animals(request_id, response, exception):
      \"\"\"Do something with the animals list response.\"\"\"
      if exception is not None:
        # Do something with the exception.
        pass
      else:
        # Do something with the response.
        pass

    def list_farmers(request_id, response, exception):
      \"\"\"Do something with the farmers list response.\"\"\"
      if exception is not None:
        # Do something with the exception.
        pass
      else:
        # Do something with the response.
        pass

    service = build('farm', 'v2')

    batch = BatchHttpRequest()

    batch.add(service.animals().list(), list_animals)
    batch.add(service.farmers().list(), list_farmers)
    batch.execute(http=http)
  """

    @util.positional(1)
    def __init__(self, callback=None, batch_uri=None):
        """Constructor for a BatchHttpRequest.

    Args:
      callback: callable, A callback to be called for each response, of the
        form callback(id, response, exception). The first parameter is the
        request id, and the second is the deserialized response object. The
        third is an googleapiclient.errors.HttpError exception object if an HTTP error
        occurred while processing the request, or None if no error occurred.
      batch_uri: string, URI to send batch requests to.
    """
        if batch_uri is None:
            batch_uri = _LEGACY_BATCH_URI

        if batch_uri == _LEGACY_BATCH_URI:
            LOGGER.warning(
                "You have constructed a BatchHttpRequest using the legacy batch "
                "endpoint %s. This endpoint will be turned down on August 12, 2020. "
                "Please provide the API-specific endpoint or use "
                "service.new_batch_http_request(). For more details see "
                "https://developers.googleblog.com/2018/03/discontinuing-support-for-json-rpc-and.html"
                "and https://developers.google.com/api-client-library/python/guide/batch.",
                _LEGACY_BATCH_URI,
            )
        self._batch_uri = batch_uri

        # Global callback to be called for each individual response in the batch.
        self._callback = callback

        # A map from id to request.
        self._requests = {}

        # A map from id to callback.
        self._callbacks = {}

        # List of request ids, in the order in which they were added.
        self._order = []

        # The last auto generated id.
        self._last_auto_id = 0

        # Unique ID on which to base the Content-ID headers.
        self._base_id = None

        # A map from request id to (httplib2.Response, content) response pairs
        self._responses = {}

        # A map of id(Credentials) that have been refreshed.
        self._refreshed_credentials = {}

    def _refresh_and_apply_credentials(self, request, http):
        """Refresh the credentials and apply to the request.

    Args:
      request: HttpRequest, the request.
      http: httplib2.Http, the global http object for the batch.
    """
        # For the credentials to refresh, but only once per refresh_token
        # If there is no http per the request then refresh the http passed in
        # via execute()
        creds = None
        request_credentials = False

        if request.http is not None:
            creds = _auth.get_credentials_from_http(request.http)
            request_credentials = True

        if creds is None and http is not None:
            creds = _auth.get_credentials_from_http(http)

        if creds is not None:
            if id(creds) not in self._refreshed_credentials:
                _auth.refresh_credentials(creds)
                self._refreshed_credentials[id(creds)] = 1

        # Only apply the credentials if we are using the http object passed in,
        # otherwise apply() will get called during _serialize_request().
        if request.http is None or not request_credentials:
            _auth.apply_credentials(creds, request.headers)

    def _id_to_header(self, id_):
        """Convert an id to a Content-ID header value.

    Args:
      id_: string, identifier of individual request.

    Returns:
      A Content-ID header with the id_ encoded into it. A UUID is prepended to
      the value because Content-ID headers are supposed to be universally
      unique.
    """
        if self._base_id is None:
            self._base_id = uuid.uuid4()

        # NB: we intentionally leave whitespace between base/id and '+', so RFC2822
        # line folding works properly on Python 3; see
        # https://github.com/googleapis/google-api-python-client/issues/164
        return "<%s + %s>" % (self._base_id, quote(id_))

    def _header_to_id(self, header):
        """Convert a Content-ID header value to an id.

    Presumes the Content-ID header conforms to the format that _id_to_header()
    returns.

    Args:
      header: string, Content-ID header value.

    Returns:
      The extracted id value.

    Raises:
      BatchError if the header is not in the expected format.
    """
        if header[0] != "<" or header[-1] != ">":
            raise BatchError("Invalid value for Content-ID: %s" % header)
        if "+" not in header:
            raise BatchError("Invalid value for Content-ID: %s" % header)
        base, id_ = header[1:-1].split(" + ", 1)

        return unquote(id_)

    def _serialize_request(self, request):
        """Convert an HttpRequest object into a string.

    Args:
      request: HttpRequest, the request to serialize.

    Returns:
      The request as a string in application/http format.
    """
        # Construct status line
        parsed = urlparse(request.uri)
        request_line = urlunparse(
            ("", "", parsed.path, parsed.params, parsed.query, "")
        )
        status_line = request.method + " " + request_line + " HTTP/1.1\n"
        major, minor = request.headers.get("content-type", "application/json").split(
            "/"
        )
        msg = MIMENonMultipart(major, minor)
        headers = request.headers.copy()

        if request.http is not None:
            credentials = _auth.get_credentials_from_http(request.http)
            if credentials is not None:
                _auth.apply_credentials(credentials, headers)

        # MIMENonMultipart adds its own Content-Type header.
        if "content-type" in headers:
            del headers["content-type"]

        for key, value in six.iteritems(headers):
            msg[key] = value
        msg["Host"] = parsed.netloc
        msg.set_unixfrom(None)

        if request.body is not None:
            msg.set_payload(request.body)
            msg["content-length"] = str(len(request.body))

        # Serialize the mime message.
        fp = StringIO()
        # maxheaderlen=0 means don't line wrap headers.
        g = Generator(fp, maxheaderlen=0)
        g.flatten(msg, unixfrom=False)
        body = fp.getvalue()

        return status_line + body

    def _deserialize_response(self, payload):
        """Convert string into httplib2 response and content.

    Args:
      payload: string, headers and body as a string.

    Returns:
      A pair (resp, content), such as would be returned from httplib2.request.
    """
        # Strip off the status line
        status_line, payload = payload.split("\n", 1)
        protocol, status, reason = status_line.split(" ", 2)

        # Parse the rest of the response
        parser = FeedParser()
        parser.feed(payload)
        msg = parser.close()
        msg["status"] = status

        # Create httplib2.Response from the parsed headers.
        resp = httplib2.Response(msg)
        resp.reason = reason
        resp.version = int(protocol.split("/", 1)[1].replace(".", ""))

        content = payload.split("\r\n\r\n", 1)[1]

        return resp, content

    def _new_id(self):
        """Create a new id.

    Auto incrementing number that avoids conflicts with ids already used.

    Returns:
       string, a new unique id.
    """
        self._last_auto_id += 1
        while str(self._last_auto_id) in self._requests:
            self._last_auto_id += 1
        return str(self._last_auto_id)

    @util.positional(2)
    def add(self, request, callback=None, request_id=None):
        """Add a new request.

    Every callback added will be paired with a unique id, the request_id. That
    unique id will be passed back to the callback when the response comes back
    from the server. The default behavior is to have the library generate it's
    own unique id. If the caller passes in a request_id then they must ensure
    uniqueness for each request_id, and if they are not an exception is
    raised. Callers should either supply all request_ids or never supply a
    request id, to avoid such an error.

    Args:
      request: HttpRequest, Request to add to the batch.
      callback: callable, A callback to be called for this response, of the
        form callback(id, response, exception). The first parameter is the
        request id, and the second is the deserialized response object. The
        third is an googleapiclient.errors.HttpError exception object if an HTTP error
        occurred while processing the request, or None if no errors occurred.
      request_id: string, A unique id for the request. The id will be passed
        to the callback with the response.

    Returns:
      None

    Raises:
      BatchError if a media request is added to a batch.
      KeyError is the request_id is not unique.
    """

        if len(self._order) >= MAX_BATCH_LIMIT:
            raise BatchError(
                "Exceeded the maximum calls(%d) in a single batch request."
                % MAX_BATCH_LIMIT
            )
        if request_id is None:
            request_id = self._new_id()
        if request.resumable is not None:
            raise BatchError("Media requests cannot be used in a batch request.")
        if request_id in self._requests:
            raise KeyError("A request with this ID already exists: %s" % request_id)
        self._requests[request_id] = request
        self._callbacks[request_id] = callback
        self._order.append(request_id)

    def _execute(self, http, order, requests):
        """Serialize batch request, send to server, process response.

    Args:
      http: httplib2.Http, an http object to be used to make the request with.
      order: list, list of request ids in the order they were added to the
        batch.
      requests: list, list of request objects to send.

    Raises:
      httplib2.HttpLib2Error if a transport error has occurred.
      googleapiclient.errors.BatchError if the response is the wrong format.
    """
        message = MIMEMultipart("mixed")
        # Message should not write out it's own headers.
        setattr(message, "_write_headers", lambda self: None)

        # Add all the individual requests.
        for request_id in order:
            request = requests[request_id]

            msg = MIMENonMultipart("application", "http")
            msg["Content-Transfer-Encoding"] = "binary"
            msg["Content-ID"] = self._id_to_header(request_id)

            body = self._serialize_request(request)
            msg.set_payload(body)
            message.attach(msg)

        # encode the body: note that we can't use `as_string`, because
        # it plays games with `From ` lines.
        fp = StringIO()
        g = Generator(fp, mangle_from_=False)
        g.flatten(message, unixfrom=False)
        body = fp.getvalue()

        headers = {}
        headers["content-type"] = (
            "multipart/mixed; " 'boundary="%s"'
        ) % message.get_boundary()

        resp, content = http.request(
            self._batch_uri, method="POST", body=body, headers=headers
        )

        if resp.status >= 300:
            raise HttpError(resp, content, uri=self._batch_uri)

        # Prepend with a content-type header so FeedParser can handle it.
        header = "content-type: %s\r\n\r\n" % resp["content-type"]
        # PY3's FeedParser only accepts unicode. So we should decode content
        # here, and encode each payload again.
        if six.PY3:
            content = content.decode("utf-8")
        for_parser = header + content

        parser = FeedParser()
        parser.feed(for_parser)
        mime_response = parser.close()

        if not mime_response.is_multipart():
            raise BatchError(
                "Response not in multipart/mixed format.", resp=resp, content=content
            )

        for part in mime_response.get_payload():
            request_id = self._header_to_id(part["Content-ID"])
            response, content = self._deserialize_response(part.get_payload())
            # We encode content here to emulate normal http response.
            if isinstance(content, six.text_type):
                content = content.encode("utf-8")
            self._responses[request_id] = (response, content)

    @util.positional(1)
    def execute(self, http=None):
        """Execute all the requests as a single batched HTTP request.

    Args:
      http: httplib2.Http, an http object to be used in place of the one the
        HttpRequest request object was constructed with. If one isn't supplied
        then use a http object from the requests in this batch.

    Returns:
      None

    Raises:
      httplib2.HttpLib2Error if a transport error has occurred.
      googleapiclient.errors.BatchError if the response is the wrong format.
    """
        # If we have no requests return
        if len(self._order) == 0:
            return None

        # If http is not supplied use the first valid one given in the requests.
        if http is None:
            for request_id in self._order:
                request = self._requests[request_id]
                if request is not None:
                    http = request.http
                    break

        if http is None:
            raise ValueError("Missing a valid http object.")

        # Special case for OAuth2Credentials-style objects which have not yet been
        # refreshed with an initial access_token.
        creds = _auth.get_credentials_from_http(http)
        if creds is not None:
            if not _auth.is_valid(creds):
                LOGGER.info("Attempting refresh to obtain initial access_token")
                _auth.refresh_credentials(creds)

        self._execute(http, self._order, self._requests)

        # Loop over all the requests and check for 401s. For each 401 request the
        # credentials should be refreshed and then sent again in a separate batch.
        redo_requests = {}
        redo_order = []

        for request_id in self._order:
            resp, content = self._responses[request_id]
            if resp["status"] == "401":
                redo_order.append(request_id)
                request = self._requests[request_id]
                self._refresh_and_apply_credentials(request, http)
                redo_requests[request_id] = request

        if redo_requests:
            self._execute(http, redo_order, redo_requests)

        # Now process all callbacks that are erroring, and raise an exception for
        # ones that return a non-2xx response? Or add extra parameter to callback
        # that contains an HttpError?

        for request_id in self._order:
            resp, content = self._responses[request_id]

            request = self._requests[request_id]
            callback = self._callbacks[request_id]

            response = None
            exception = None
            try:
                if resp.status >= 300:
                    raise HttpError(resp, content, uri=request.uri)
                response = request.postproc(resp, content)
            except HttpError as e:
                exception = e

            if callback is not None:
                callback(request_id, response, exception)
            if self._callback is not None:
                self._callback(request_id, response, exception)


class HttpRequestMock(object):
    """Mock of HttpRequest.

  Do not construct directly, instead use RequestMockBuilder.
  """

    def __init__(self, resp, content, postproc):
        """Constructor for HttpRequestMock

    Args:
      resp: httplib2.Response, the response to emulate coming from the request
      content: string, the response body
      postproc: callable, the post processing function usually supplied by
                the model class. See model.JsonModel.response() as an example.
    """
        self.resp = resp
        self.content = content
        self.postproc = postproc
        if resp is None:
            self.resp = httplib2.Response({"status": 200, "reason": "OK"})
        if "reason" in self.resp:
            self.resp.reason = self.resp["reason"]

    def execute(self, http=None):
        """Execute the request.

    Same behavior as HttpRequest.execute(), but the response is
    mocked and not really from an HTTP request/response.
    """
        return self.postproc(self.resp, self.content)


class RequestMockBuilder(object):
    """A simple mock of HttpRequest

    Pass in a dictionary to the constructor that maps request methodIds to
    tuples of (httplib2.Response, content, opt_expected_body) that should be
    returned when that method is called. None may also be passed in for the
    httplib2.Response, in which case a 200 OK response will be generated.
    If an opt_expected_body (str or dict) is provided, it will be compared to
    the body and UnexpectedBodyError will be raised on inequality.

    Example:
      response = '{"data": {"id": "tag:google.c...'
      requestBuilder = RequestMockBuilder(
        {
          'plus.activities.get': (None, response),
        }
      )
      googleapiclient.discovery.build("plus", "v1", requestBuilder=requestBuilder)

    Methods that you do not supply a response for will return a
    200 OK with an empty string as the response content or raise an excpetion
    if check_unexpected is set to True. The methodId is taken from the rpcName
    in the discovery document.

    For more details see the project wiki.
  """

    def __init__(self, responses, check_unexpected=False):
        """Constructor for RequestMockBuilder

    The constructed object should be a callable object
    that can replace the class HttpResponse.

    responses - A dictionary that maps methodIds into tuples
                of (httplib2.Response, content). The methodId
                comes from the 'rpcName' field in the discovery
                document.
    check_unexpected - A boolean setting whether or not UnexpectedMethodError
                       should be raised on unsupplied method.
    """
        self.responses = responses
        self.check_unexpected = check_unexpected

    def __call__(
        self,
        http,
        postproc,
        uri,
        method="GET",
        body=None,
        headers=None,
        methodId=None,
        resumable=None,
    ):
        """Implements the callable interface that discovery.build() expects
    of requestBuilder, which is to build an object compatible with
    HttpRequest.execute(). See that method for the description of the
    parameters and the expected response.
    """
        if methodId in self.responses:
            response = self.responses[methodId]
            resp, content = response[:2]
            if len(response) > 2:
                # Test the body against the supplied expected_body.
                expected_body = response[2]
                if bool(expected_body) != bool(body):
                    # Not expecting a body and provided one
                    # or expecting a body and not provided one.
                    raise UnexpectedBodyError(expected_body, body)
                if isinstance(expected_body, str):
                    expected_body = json.loads(expected_body)
                body = json.loads(body)
                if body != expected_body:
                    raise UnexpectedBodyError(expected_body, body)
            return HttpRequestMock(resp, content, postproc)
        elif self.check_unexpected:
            raise UnexpectedMethodError(methodId=methodId)
        else:
            model = JsonModel(False)
            return HttpRequestMock(None, "{}", model.response)


class HttpMock(object):
    """Mock of httplib2.Http"""

    def __init__(self, filename=None, headers=None):
        """
    Args:
      filename: string, absolute filename to read response from
      headers: dict, header to return with response
    """
        if headers is None:
            headers = {"status": "200"}
        if filename:
            with open(filename, "rb") as f:
                self.data = f.read()
        else:
            self.data = None
        self.response_headers = headers
        self.headers = None
        self.uri = None
        self.method = None
        self.body = None
        self.headers = None

    def request(
        self,
        uri,
        method="GET",
        body=None,
        headers=None,
        redirections=1,
        connection_type=None,
    ):
        self.uri = uri
        self.method = method
        self.body = body
        self.headers = headers
        return httplib2.Response(self.response_headers), self.data

    def close(self):
        return None

class HttpMockSequence(object):
    """Mock of httplib2.Http

  Mocks a sequence of calls to request returning different responses for each
  call. Create an instance initialized with the desired response headers
  and content and then use as if an httplib2.Http instance.

    http = HttpMockSequence([
      ({'status': '401'}, ''),
      ({'status': '200'}, '{"access_token":"1/3w","expires_in":3600}'),
      ({'status': '200'}, 'echo_request_headers'),
      ])
    resp, content = http.request("http://examples.com")

  There are special values you can pass in for content to trigger
  behavours that are helpful in testing.

  'echo_request_headers' means return the request headers in the response body
  'echo_request_headers_as_json' means return the request headers in
     the response body
  'echo_request_body' means return the request body in the response body
  'echo_request_uri' means return the request uri in the response body
  """

    def __init__(self, iterable):
        """
    Args:
      iterable: iterable, a sequence of pairs of (headers, body)
    """
        self._iterable = iterable
        self.follow_redirects = True
        self.request_sequence = list()

    def request(
        self,
        uri,
        method="GET",
        body=None,
        headers=None,
        redirections=1,
        connection_type=None,
    ):
        # Remember the request so after the fact this mock can be examined
        self.request_sequence.append((uri, method, body, headers))
        resp, content = self._iterable.pop(0)
        content = six.ensure_binary(content)

        if content == b"echo_request_headers":
            content = headers
        elif content == b"echo_request_headers_as_json":
            content = json.dumps(headers)
        elif content == b"echo_request_body":
            if hasattr(body, "read"):
                content = body.read()
            else:
                content = body
        elif content == b"echo_request_uri":
            content = uri
        if isinstance(content, six.text_type):
            content = content.encode("utf-8")
        return httplib2.Response(resp), content


def set_user_agent(http, user_agent):
    """Set the user-agent on every request.

  Args:
     http - An instance of httplib2.Http
         or something that acts like it.
     user_agent: string, the value for the user-agent header.

  Returns:
     A modified instance of http that was passed in.

  Example:

    h = httplib2.Http()
    h = set_user_agent(h, "my-app-name/6.0")

  Most of the time the user-agent will be set doing auth, this is for the rare
  cases where you are accessing an unauthenticated endpoint.
  """
    request_orig = http.request

    # The closure that will replace 'httplib2.Http.request'.
    def new_request(
        uri,
        method="GET",
        body=None,
        headers=None,
        redirections=httplib2.DEFAULT_MAX_REDIRECTS,
        connection_type=None,
    ):
        """Modify the request headers to add the user-agent."""
        if headers is None:
            headers = {}
        if "user-agent" in headers:
            headers["user-agent"] = user_agent + " " + headers["user-agent"]
        else:
            headers["user-agent"] = user_agent
        resp, content = request_orig(
            uri,
            method=method,
            body=body,
            headers=headers,
            redirections=redirections,
            connection_type=connection_type,
        )
        return resp, content

    http.request = new_request
    return http


def tunnel_patch(http):
    """Tunnel PATCH requests over POST.
  Args:
     http - An instance of httplib2.Http
         or something that acts like it.

  Returns:
     A modified instance of http that was passed in.

  Example:

    h = httplib2.Http()
    h = tunnel_patch(h, "my-app-name/6.0")

  Useful if you are running on a platform that doesn't support PATCH.
  Apply this last if you are using OAuth 1.0, as changing the method
  will result in a different signature.
  """
    request_orig = http.request

    # The closure that will replace 'httplib2.Http.request'.
    def new_request(
        uri,
        method="GET",
        body=None,
        headers=None,
        redirections=httplib2.DEFAULT_MAX_REDIRECTS,
        connection_type=None,
    ):
        """Modify the request headers to add the user-agent."""
        if headers is None:
            headers = {}
        if method == "PATCH":
            if "oauth_token" in headers.get("authorization", ""):
                LOGGER.warning(
                    "OAuth 1.0 request made with Credentials after tunnel_patch."
                )
            headers["x-http-method-override"] = "PATCH"
            method = "POST"
        resp, content = request_orig(
            uri,
            method=method,
            body=body,
            headers=headers,
            redirections=redirections,
            connection_type=connection_type,
        )
        return resp, content

    http.request = new_request
    return http


def build_http():
    """Builds httplib2.Http object

  Returns:
  A httplib2.Http object, which is used to make http requests, and which has timeout set by default.
  To override default timeout call

    socket.setdefaulttimeout(timeout_in_sec)

  before interacting with this method.
  """
    if socket.getdefaulttimeout() is not None:
        http_timeout = socket.getdefaulttimeout()
    else:
        http_timeout = DEFAULT_HTTP_TIMEOUT_SEC
    http = httplib2.Http(timeout=http_timeout)
    # 308's are used by several Google APIs (Drive, YouTube)
    # for Resumable Uploads rather than Permanent Redirects.
    # This asks httplib2 to exclude 308s from the status codes
    # it treats as redirects
    try:
      http.redirect_codes = http.redirect_codes - {308}
    except AttributeError:
      # Apache Beam tests depend on this library and cannot
      # currently upgrade their httplib2 version
      # http.redirect_codes does not exist in previous versions
      # of httplib2, so pass
      pass

    return http
