def api_request(uri, method="GET", data=None, params=None, timeout=4): """ Invoke an API request to the given URI, returning JSON data from the response as a dict. :param uri: The request URI. :type uri: string :param method: The HTTP method, defaults to "GET". :type method: string, optional :param data: The request body. :type data: dict, optional :param params: The URL parameters. :type params: list, optional :param timeout: The request timeout, in seconds. :type timeout: float, optional :return: The response from the request. :rtype: dict """ if params is None: params = [] data = json.dumps(data).encode("utf-8") if data else None if params: uri += "?{}".format(urlencode([(x, params[x]) for x in params])) request = Request(uri, method=method.upper()) request.add_header("Content-Type", "application/json") logger.debug("Making {} request to {} with data: {}".format( method, uri, data)) try: response = urlopen(request, data, timeout) response_data = response.read().decode("utf-8") status_code = response.getcode() logger.debug("Response status code: {}".format(status_code)) logger.debug("Response: {}".format(response_data)) if str(status_code)[0] != "2": raise PyngrokNgrokHTTPError( "ngrok client API returned {}: {}".format( status_code, response_data), uri, status_code, None, request.headers, response_data) elif status_code == 204: return None return json.loads(response_data) except socket.timeout: raise PyngrokNgrokURLError( "ngrok client exception, URLError: timed out", "timed out") except HTTPError as e: response_data = e.read().decode("utf-8") status_code = e.getcode() logger.debug("Response status code: {}".format(status_code)) logger.debug("Response: {}".format(response_data)) raise PyngrokNgrokHTTPError( "ngrok client exception, API returned {}: {}".format( status_code, response_data), e.url, status_code, e.msg, e.hdrs, response_data) except URLError as e: raise PyngrokNgrokURLError( "ngrok client exception, URLError: {}".format(e.reason), e.reason)
def api_request(url, method="GET", data=None, params=None, timeout=4): """ Invoke an API request to the given URL, returning JSON data from the response. One use for this method is making requests to ``ngrok`` tunnels: .. code-block:: python from pyngrok import ngrok public_url = ngrok.connect() response = ngrok.api_request("{}/some-route".format(public_url), method="POST", data={"foo": "bar"}) Another is making requests to the ``ngrok`` API itself: .. code-block:: python from pyngrok import ngrok api_url = ngrok.get_ngrok_process().api_url response = ngrok.api_request("{}/api/requests/http".format(api_url), params={"tunnel_name": "foo"}) :param url: The request URL. :type url: str :param method: The HTTP method. :type method: str, optional :param data: The request body. :type data: dict, optional :param params: The URL parameters. :type params: dict, optional :param timeout: The request timeout, in seconds. :type timeout: float, optional :return: The response from the request. :rtype: dict """ if params is None: params = [] if not url.lower().startswith("http"): raise PyngrokSecurityError( "URL must start with \"http\": {}".format(url)) data = json.dumps(data).encode("utf-8") if data else None if params: url += "?{}".format(urlencode([(x, params[x]) for x in params])) request = Request(url, method=method.upper()) request.add_header("Content-Type", "application/json") logger.debug("Making {} request to {} with data: {}".format( method, url, data)) try: response = urlopen(request, data, timeout) response_data = response.read().decode("utf-8") status_code = response.getcode() logger.debug("Response {}: {}".format(status_code, response_data.strip())) if str(status_code)[0] != "2": raise PyngrokNgrokHTTPError( "ngrok client API returned {}: {}".format( status_code, response_data), url, status_code, None, request.headers, response_data) elif status_code == HTTPStatus.NO_CONTENT: return None return json.loads(response_data) except socket.timeout: raise PyngrokNgrokURLError( "ngrok client exception, URLError: timed out", "timed out") except HTTPError as e: response_data = e.read().decode("utf-8") status_code = e.getcode() logger.debug("Response {}: {}".format(status_code, response_data.strip())) raise PyngrokNgrokHTTPError( "ngrok client exception, API returned {}: {}".format( status_code, response_data), e.url, status_code, e.msg, e.hdrs, response_data) except URLError as e: raise PyngrokNgrokURLError( "ngrok client exception, URLError: {}".format(e.reason), e.reason)