Exemplo n.º 1
0
    def request(self,
                url,
                first_request_time=None,
                retry_counter=0,
                post_json=None):
        """Performs HTTP GET/POST with credentials, returning the body as
        JSON.

        :param url: URL extension for request. Should begin with a slash.
        :type url: string

        :param first_request_time: The time of the first request (None if no
            retries have occurred).
        :type first_request_time: datetime.datetime

        :param post_json: Parameters for POST endpoints
        :type post_json: dict

        :raises valhalla.utils.exceptions.ApiError: when the API returns an error.

        :returns: openrouteservice response body
        :rtype: dict
        """

        if not first_request_time:
            first_request_time = datetime.now()

        elapsed = datetime.now() - first_request_time
        if elapsed > self.retry_timeout:
            raise 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=1. The first retry will occur
            # at 1, so subtract that first.
            delay_seconds = 1.5**(retry_counter - 1)

            # Jitter this value by 50% and pause.
            time.sleep(delay_seconds * (random.random() + 0.5))

        # Define the request
        params = {'access_token': self.key}
        authed_url = self._generate_auth_url(
            url,
            params,
        )
        url_object = QUrl(self.base_url + authed_url)
        self.url = url_object.url()
        body = QJsonDocument.fromJson(json.dumps(post_json).encode())
        request = QNetworkRequest(url_object)
        request.setHeader(QNetworkRequest.ContentTypeHeader,
                          'application/json')

        logger.log(
            "url: {}\nParameters: {}".format(
                self.url,
                # final_requests_kwargs
                json.dumps(post_json, indent=2)),
            0)

        start = time.time()
        response: QgsNetworkReplyContent = self.nam.blockingPost(
            request, body.toJson())
        self.response_time = time.time() - start

        try:
            self.handle_response(response, post_json['id'])
        except exceptions.OverQueryLimit:
            # Let the instances know smth happened
            self.overQueryLimit.emit()
            return self.request(url, first_request_time, retry_counter + 1,
                                post_json)

        response_content = json.loads(bytes(response.content()))

        # Mapbox treats 400 errors with a 200 status code
        if 'error' in response_content:
            raise exceptions.ApiError(str(response_content['status_code']),
                                      response_content['error'])

        return response_content