Spaces:
Sleeping
Sleeping
| import io | |
| import json | |
| import re | |
| import requests | |
| from requests.adapters import HTTPAdapter | |
| from six.moves.urllib.parse import urlencode | |
| from urllib3 import Retry | |
| class RESTResponse(io.IOBase): | |
| def __init__(self, resp): | |
| self.status = resp.status_code | |
| self.reason = resp.reason | |
| self.resp = resp | |
| self.headers = resp.headers | |
| def getheaders(self): | |
| return self.headers | |
| class RESTClientObject(object): | |
| def __init__(self, connection=None): | |
| self.connection = connection or requests.Session() | |
| retry_strategy = Retry( | |
| total=3, | |
| backoff_factor=2, | |
| status_forcelist=[429, 500, 502, 503, 504], | |
| allowed_methods=[ | |
| "HEAD", | |
| "GET", | |
| "OPTIONS", | |
| "DELETE", | |
| ], # all the methods that are supposed to be idempotent | |
| ) | |
| self.connection.mount("https://", HTTPAdapter(max_retries=retry_strategy)) | |
| self.connection.mount("http://", HTTPAdapter(max_retries=retry_strategy)) | |
| def request( | |
| self, | |
| method, | |
| url, | |
| query_params=None, | |
| headers=None, | |
| body=None, | |
| post_params=None, | |
| _preload_content=True, | |
| _request_timeout=None, | |
| ): | |
| """Perform requests. | |
| :param method: http request method | |
| :param url: http request url | |
| :param query_params: query parameters in the url | |
| :param headers: http request headers | |
| :param body: request json body, for `application/json` | |
| :param post_params: request post parameters, | |
| `application/x-www-form-urlencoded` | |
| and `multipart/form-data` | |
| :param _preload_content: if False, the urllib3.HTTPResponse object will | |
| be returned without reading/decoding response | |
| data. Default is True. | |
| :param _request_timeout: timeout setting for this request. If one | |
| number provided, it will be total request | |
| timeout. It can also be a pair (tuple) of | |
| (connection, read) timeouts. | |
| """ | |
| method = method.upper() | |
| assert method in ["GET", "HEAD", "DELETE", "POST", "PUT", "PATCH", "OPTIONS"] | |
| if post_params and body: | |
| raise ValueError( | |
| "body parameter cannot be used with post_params parameter." | |
| ) | |
| post_params = post_params or {} | |
| headers = headers or {} | |
| timeout = _request_timeout if _request_timeout is not None else (120, 120) | |
| if "Content-Type" not in headers: | |
| headers["Content-Type"] = "application/json" | |
| try: | |
| # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` | |
| if method in ["POST", "PUT", "PATCH", "OPTIONS", "DELETE"]: | |
| if query_params: | |
| url += "?" + urlencode(query_params) | |
| if re.search( | |
| "json", headers["Content-Type"], re.IGNORECASE | |
| ) or isinstance(body, str): | |
| request_body = "{}" | |
| if body is not None: | |
| request_body = json.dumps(body) | |
| if isinstance(body, str): | |
| request_body = request_body.strip('"') | |
| r = self.connection.request( | |
| method, url, data=request_body, timeout=timeout, headers=headers | |
| ) | |
| else: | |
| # Cannot generate the request from given parameters | |
| msg = """Cannot prepare a request message for provided | |
| arguments. Please check that your arguments match | |
| declared content type.""" | |
| raise ApiException(status=0, reason=msg) | |
| # For `GET`, `HEAD` | |
| else: | |
| r = self.connection.request( | |
| method, url, params=query_params, timeout=timeout, headers=headers | |
| ) | |
| except Exception as e: | |
| msg = "{0}\n{1}".format(type(e).__name__, str(e)) | |
| raise ApiException(status=0, reason=msg) | |
| if _preload_content: | |
| r = RESTResponse(r) | |
| if r.status == 401 or r.status == 403: | |
| raise AuthorizationException(http_resp=r) | |
| if not 200 <= r.status <= 299: | |
| raise ApiException(http_resp=r) | |
| return r | |
| def GET( | |
| self, | |
| url, | |
| headers=None, | |
| query_params=None, | |
| _preload_content=True, | |
| _request_timeout=None, | |
| ): | |
| return self.request( | |
| "GET", | |
| url, | |
| headers=headers, | |
| _preload_content=_preload_content, | |
| _request_timeout=_request_timeout, | |
| query_params=query_params, | |
| ) | |
| def HEAD( | |
| self, | |
| url, | |
| headers=None, | |
| query_params=None, | |
| _preload_content=True, | |
| _request_timeout=None, | |
| ): | |
| return self.request( | |
| "HEAD", | |
| url, | |
| headers=headers, | |
| _preload_content=_preload_content, | |
| _request_timeout=_request_timeout, | |
| query_params=query_params, | |
| ) | |
| def OPTIONS( | |
| self, | |
| url, | |
| headers=None, | |
| query_params=None, | |
| post_params=None, | |
| body=None, | |
| _preload_content=True, | |
| _request_timeout=None, | |
| ): | |
| return self.request( | |
| "OPTIONS", | |
| url, | |
| headers=headers, | |
| query_params=query_params, | |
| post_params=post_params, | |
| _preload_content=_preload_content, | |
| _request_timeout=_request_timeout, | |
| body=body, | |
| ) | |
| def DELETE( | |
| self, | |
| url, | |
| headers=None, | |
| query_params=None, | |
| body=None, | |
| _preload_content=True, | |
| _request_timeout=None, | |
| ): | |
| return self.request( | |
| "DELETE", | |
| url, | |
| headers=headers, | |
| query_params=query_params, | |
| _preload_content=_preload_content, | |
| _request_timeout=_request_timeout, | |
| body=body, | |
| ) | |
| def POST( | |
| self, | |
| url, | |
| headers=None, | |
| query_params=None, | |
| post_params=None, | |
| body=None, | |
| _preload_content=True, | |
| _request_timeout=None, | |
| ): | |
| return self.request( | |
| "POST", | |
| url, | |
| headers=headers, | |
| query_params=query_params, | |
| post_params=post_params, | |
| _preload_content=_preload_content, | |
| _request_timeout=_request_timeout, | |
| body=body, | |
| ) | |
| def PUT( | |
| self, | |
| url, | |
| headers=None, | |
| query_params=None, | |
| post_params=None, | |
| body=None, | |
| _preload_content=True, | |
| _request_timeout=None, | |
| ): | |
| return self.request( | |
| "PUT", | |
| url, | |
| headers=headers, | |
| query_params=query_params, | |
| post_params=post_params, | |
| _preload_content=_preload_content, | |
| _request_timeout=_request_timeout, | |
| body=body, | |
| ) | |
| def PATCH( | |
| self, | |
| url, | |
| headers=None, | |
| query_params=None, | |
| post_params=None, | |
| body=None, | |
| _preload_content=True, | |
| _request_timeout=None, | |
| ): | |
| return self.request( | |
| "PATCH", | |
| url, | |
| headers=headers, | |
| query_params=query_params, | |
| post_params=post_params, | |
| _preload_content=_preload_content, | |
| _request_timeout=_request_timeout, | |
| body=body, | |
| ) | |
| class ApiException(Exception): | |
| def __init__(self, status=None, reason=None, http_resp=None, body=None): | |
| if http_resp: | |
| self.status = http_resp.status | |
| self.code = http_resp.status | |
| self.reason = http_resp.reason | |
| self.body = http_resp.resp.text | |
| try: | |
| if http_resp.resp.text: | |
| error = json.loads(http_resp.resp.text) | |
| self.message = error["message"] | |
| else: | |
| self.message = http_resp.resp.text | |
| except Exception as e: | |
| self.message = http_resp.resp.text | |
| self.headers = http_resp.getheaders() | |
| else: | |
| self.status = status | |
| self.code = status | |
| self.reason = reason | |
| self.body = body | |
| self.message = body | |
| self.headers = None | |
| def __str__(self): | |
| """Custom error messages for exception""" | |
| error_message = "({0})\n" "Reason: {1}\n".format(self.status, self.reason) | |
| if self.headers: | |
| error_message += "HTTP response headers: {0}\n".format(self.headers) | |
| if self.body: | |
| error_message += "HTTP response body: {0}\n".format(self.body) | |
| return error_message | |
| def is_not_found(self) -> bool: | |
| return self.code == 404 | |
| class AuthorizationException(ApiException): | |
| def __init__(self, status=None, reason=None, http_resp=None, body=None): | |
| try: | |
| data = json.loads(http_resp.resp.text) | |
| if "error" in data: | |
| self._error_code = data["error"] | |
| else: | |
| self._error_code = "" | |
| except Exception: | |
| self._error_code = "" | |
| super().__init__(status, reason, http_resp, body) | |
| def error_code(self): | |
| return self._error_code | |
| def status_code(self): | |
| return self.status | |
| def token_expired(self) -> bool: | |
| return self._error_code == "EXPIRED_TOKEN" | |
| def invalid_token(self) -> bool: | |
| return self._error_code == "INVALID_TOKEN" | |
| def __str__(self): | |
| """Custom error messages for exception""" | |
| error_message = f"authorization error: {self._error_code}. status_code: {self.status}, reason: {self.reason}" | |
| if self.headers: | |
| error_message += f", headers: {self.headers}" | |
| if self.body: | |
| error_message += f", response: {self.body}" | |
| return error_message | |