docs: def _request(self, url, params, first_request_time=None, retry_counter=0,
               base_url=_DEFAULT_BASE_URL, accepts_clientid=True,
               extract_body=None, requests_kwargs=None, post_json=None):
          """Performs HTTP GET/POST with credentials, returning the body as
          JSON.
  
          :param url: URL path for the request. Should begin with a slash.
          :type url: string
  
          :param params: HTTP GET parameters.
          :type params: dict or list of key/value tuples
  
          :param first_request_time: The time of the first request (None if no
              retries have occurred).
          :type first_request_time: datetime.datetime
  
          :param retry_counter: The number of this retry, or zero for first attempt.
          :type retry_counter: int
  
          :param base_url: The base URL for the request. Defaults to the Maps API
              server. Should not have a trailing slash.
          :type base_url: string
  
          :param accepts_clientid: Whether this call supports the client/signature
              params. Some APIs require API keys (e.g. Roads).
          :type accepts_clientid: bool
  
          :param extract_body: A function that extracts the body from the request.
              If the request was not successful, the function should raise a
              googlemaps.HTTPError or googlemaps.ApiError as appropriate.
          :type extract_body: function
  
          :param requests_kwargs: Same extra keywords arg for requests as per
              __init__, but provided here to allow overriding internally on a
              per-request basis.
          :type requests_kwargs: dict
  
          :raises ApiError: when the API returns an error.
          :raises Timeout: if the request timed out.
          :raises TransportError: when something went wrong while trying to
              exceute a request.
          """
  
          if not first_request_time:
              first_request_time = datetime.now()
  
          elapsed = datetime.now() - first_request_time
          if elapsed > self.retry_timeout:
              raise googlemaps.exceptions.Timeout()
  
          if retry_counter > 0:
              # 0.5 * (1.5 ^ i) is an increased sleep time of 1.5x per iteration,
              # starting at 0.5s when retry_counter=0. The first retry will occur
              # at 1, so subtract that first.
              delay_seconds = 0.5 * 1.5 ** (retry_counter - 1)
  
              # Jitter this value by 50% and pause.
              time.sleep(delay_seconds * (random.random() + 0.5))
  
          authed_url = self._generate_auth_url(url, params, accepts_clientid)
  
          # Default to the client-level self.requests_kwargs, with method-level
          # requests_kwargs arg overriding.
          requests_kwargs = requests_kwargs or {}
          final_requests_kwargs = dict(self.requests_kwargs, **requests_kwargs)
  
          # Determine GET/POST.
          requests_method = self.session.get
          if post_json is not None:
              requests_method = self.session.post
              final_requests_kwargs["json"] = post_json
  
          try:
              response = requests_method(base_url + authed_url,
                                         **final_requests_kwargs)
          except requests.exceptions.Timeout:
              raise googlemaps.exceptions.Timeout()
          except Exception as e:
              raise googlemaps.exceptions.TransportError(e)
  
          if response.status_code in _RETRIABLE_STATUSES:
              # Retry request.
              return self._request(url, params, first_request_time,
                                   retry_counter + 1, base_url, accepts_clientid,
                                   extract_body, requests_kwargs, post_json)
  
          # Check if the time of the nth previous query (where n is
          # queries_per_second) is under a second ago - if so, sleep for
          # the difference.
          if self.sent_times and len(self.sent_times) == self.queries_per_second:
              elapsed_since_earliest = time.time() - self.sent_times[0]
              if elapsed_since_earliest < 1:
                  time.sleep(1 - elapsed_since_earliest)
  
          try:
              if extract_body:
                  result = extract_body(response)
              else:
                  result = self._get_body(response)
              self.sent_times.append(time.time())
              return result
          except googlemaps.exceptions._RetriableRequest as e:
              if isinstance(e, googlemaps.exceptions._OverQueryLimit) and not self.retry_over_query_limit:
                  raise
  
              # Retry request.
              return self._request(url, params, first_request_time,
                                   retry_counter + 1, base_url, accepts_clientid,
                                   extract_body, requests_kwargs, post_json)