github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/clients/python/bacalhau_apiclient/rest.py (about)

     1  # coding: utf-8
     2  
     3  """
     4      Bacalhau API
     5  
     6      This page is the reference of the Bacalhau REST API. Project docs are available at https://docs.bacalhau.org/. Find more information about Bacalhau at https://github.com/filecoin-project/bacalhau.  # noqa: E501
     7  
     8      OpenAPI spec version: 0.3.22.post4
     9      Contact: team@bacalhau.org
    10      Generated by: https://github.com/swagger-api/swagger-codegen.git
    11  """
    12  
    13  
    14  from __future__ import absolute_import
    15  
    16  import io
    17  import json
    18  import logging
    19  import re
    20  import ssl
    21  
    22  import certifi
    23  # python 2 and python 3 compatibility library
    24  import six
    25  from six.moves.urllib.parse import urlencode
    26  
    27  try:
    28      import urllib3
    29  except ImportError:
    30      raise ImportError('Swagger python client requires urllib3.')
    31  
    32  
    33  logger = logging.getLogger(__name__)
    34  
    35  
    36  class RESTResponse(io.IOBase):
    37  
    38      def __init__(self, resp):
    39          self.urllib3_response = resp
    40          self.status = resp.status
    41          self.reason = resp.reason
    42          self.data = resp.data
    43  
    44      def getheaders(self):
    45          """Returns a dictionary of the response headers."""
    46          return self.urllib3_response.getheaders()
    47  
    48      def getheader(self, name, default=None):
    49          """Returns a given response header."""
    50          return self.urllib3_response.getheader(name, default)
    51  
    52  
    53  class RESTClientObject(object):
    54  
    55      def __init__(self, configuration, pools_size=4, maxsize=None):
    56          # urllib3.PoolManager will pass all kw parameters to connectionpool
    57          # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75  # noqa: E501
    58          # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680  # noqa: E501
    59          # maxsize is the number of requests to host that are allowed in parallel  # noqa: E501
    60          # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html  # noqa: E501
    61  
    62          # cert_reqs
    63          if configuration.verify_ssl:
    64              cert_reqs = ssl.CERT_REQUIRED
    65          else:
    66              cert_reqs = ssl.CERT_NONE
    67  
    68          # ca_certs
    69          if configuration.ssl_ca_cert:
    70              ca_certs = configuration.ssl_ca_cert
    71          else:
    72              # if not set certificate file, use Mozilla's root certificates.
    73              ca_certs = certifi.where()
    74  
    75          addition_pool_args = {}
    76          if configuration.assert_hostname is not None:
    77              addition_pool_args['assert_hostname'] = configuration.assert_hostname  # noqa: E501
    78  
    79          if maxsize is None:
    80              if configuration.connection_pool_maxsize is not None:
    81                  maxsize = configuration.connection_pool_maxsize
    82              else:
    83                  maxsize = 4
    84  
    85          # https pool manager
    86          if configuration.proxy:
    87              self.pool_manager = urllib3.ProxyManager(
    88                  num_pools=pools_size,
    89                  maxsize=maxsize,
    90                  cert_reqs=cert_reqs,
    91                  ca_certs=ca_certs,
    92                  cert_file=configuration.cert_file,
    93                  key_file=configuration.key_file,
    94                  proxy_url=configuration.proxy,
    95                  **addition_pool_args
    96              )
    97          else:
    98              self.pool_manager = urllib3.PoolManager(
    99                  num_pools=pools_size,
   100                  maxsize=maxsize,
   101                  cert_reqs=cert_reqs,
   102                  ca_certs=ca_certs,
   103                  cert_file=configuration.cert_file,
   104                  key_file=configuration.key_file,
   105                  **addition_pool_args
   106              )
   107  
   108      def request(self, method, url, query_params=None, headers=None,
   109                  body=None, post_params=None, _preload_content=True,
   110                  _request_timeout=None):
   111          """Perform requests.
   112  
   113          :param method: http request method
   114          :param url: http request url
   115          :param query_params: query parameters in the url
   116          :param headers: http request headers
   117          :param body: request json body, for `application/json`
   118          :param post_params: request post parameters,
   119                              `application/x-www-form-urlencoded`
   120                              and `multipart/form-data`
   121          :param _preload_content: if False, the urllib3.HTTPResponse object will
   122                                   be returned without reading/decoding response
   123                                   data. Default is True.
   124          :param _request_timeout: timeout setting for this request. If one
   125                                   number provided, it will be total request
   126                                   timeout. It can also be a pair (tuple) of
   127                                   (connection, read) timeouts.
   128          """
   129          method = method.upper()
   130          assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT',
   131                            'PATCH', 'OPTIONS']
   132  
   133          if post_params and body:
   134              raise ValueError(
   135                  "body parameter cannot be used with post_params parameter."
   136              )
   137  
   138          post_params = post_params or {}
   139          headers = headers or {}
   140  
   141          timeout = None
   142          if _request_timeout:
   143              if isinstance(_request_timeout, (int, ) if six.PY3 else (int, long)):  # noqa: E501,F821
   144                  timeout = urllib3.Timeout(total=_request_timeout)
   145              elif (isinstance(_request_timeout, tuple) and
   146                    len(_request_timeout) == 2):
   147                  timeout = urllib3.Timeout(
   148                      connect=_request_timeout[0], read=_request_timeout[1])
   149  
   150          if 'Content-Type' not in headers:
   151              headers['Content-Type'] = 'application/json'
   152  
   153          try:
   154              # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
   155              if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
   156                  if query_params:
   157                      url += '?' + urlencode(query_params)
   158                  if re.search('json', headers['Content-Type'], re.IGNORECASE):
   159                      request_body = '{}'
   160                      if body is not None:
   161                          request_body = json.dumps(body)
   162                      r = self.pool_manager.request(
   163                          method, url,
   164                          body=request_body,
   165                          preload_content=_preload_content,
   166                          timeout=timeout,
   167                          headers=headers)
   168                  elif headers['Content-Type'] == 'application/x-www-form-urlencoded':  # noqa: E501
   169                      r = self.pool_manager.request(
   170                          method, url,
   171                          fields=post_params,
   172                          encode_multipart=False,
   173                          preload_content=_preload_content,
   174                          timeout=timeout,
   175                          headers=headers)
   176                  elif headers['Content-Type'] == 'multipart/form-data':
   177                      # must del headers['Content-Type'], or the correct
   178                      # Content-Type which generated by urllib3 will be
   179                      # overwritten.
   180                      del headers['Content-Type']
   181                      r = self.pool_manager.request(
   182                          method, url,
   183                          fields=post_params,
   184                          encode_multipart=True,
   185                          preload_content=_preload_content,
   186                          timeout=timeout,
   187                          headers=headers)
   188                  # Pass a `string` parameter directly in the body to support
   189                  # other content types than Json when `body` argument is
   190                  # provided in serialized form
   191                  elif isinstance(body, str):
   192                      request_body = body
   193                      r = self.pool_manager.request(
   194                          method, url,
   195                          body=request_body,
   196                          preload_content=_preload_content,
   197                          timeout=timeout,
   198                          headers=headers)
   199                  else:
   200                      # Cannot generate the request from given parameters
   201                      msg = """Cannot prepare a request message for provided
   202                               arguments. Please check that your arguments match
   203                               declared content type."""
   204                      raise ApiException(status=0, reason=msg)
   205              # For `GET`, `HEAD`
   206              else:
   207                  r = self.pool_manager.request(method, url,
   208                                                fields=query_params,
   209                                                preload_content=_preload_content,
   210                                                timeout=timeout,
   211                                                headers=headers)
   212          except urllib3.exceptions.SSLError as e:
   213              msg = "{0}\n{1}".format(type(e).__name__, str(e))
   214              raise ApiException(status=0, reason=msg)
   215  
   216          if _preload_content:
   217              r = RESTResponse(r)
   218  
   219              # In the python 3, the response.data is bytes.
   220              # we need to decode it to string.
   221              if six.PY3:
   222                  r.data = r.data.decode('utf8')
   223  
   224              # log response body
   225              logger.debug("response body: %s", r.data)
   226  
   227          if not 200 <= r.status <= 299:
   228              raise ApiException(http_resp=r)
   229  
   230          return r
   231  
   232      def GET(self, url, headers=None, query_params=None, _preload_content=True,
   233              _request_timeout=None):
   234          return self.request("GET", url,
   235                              headers=headers,
   236                              _preload_content=_preload_content,
   237                              _request_timeout=_request_timeout,
   238                              query_params=query_params)
   239  
   240      def HEAD(self, url, headers=None, query_params=None, _preload_content=True,
   241               _request_timeout=None):
   242          return self.request("HEAD", url,
   243                              headers=headers,
   244                              _preload_content=_preload_content,
   245                              _request_timeout=_request_timeout,
   246                              query_params=query_params)
   247  
   248      def OPTIONS(self, url, headers=None, query_params=None, post_params=None,
   249                  body=None, _preload_content=True, _request_timeout=None):
   250          return self.request("OPTIONS", url,
   251                              headers=headers,
   252                              query_params=query_params,
   253                              post_params=post_params,
   254                              _preload_content=_preload_content,
   255                              _request_timeout=_request_timeout,
   256                              body=body)
   257  
   258      def DELETE(self, url, headers=None, query_params=None, body=None,
   259                 _preload_content=True, _request_timeout=None):
   260          return self.request("DELETE", url,
   261                              headers=headers,
   262                              query_params=query_params,
   263                              _preload_content=_preload_content,
   264                              _request_timeout=_request_timeout,
   265                              body=body)
   266  
   267      def POST(self, url, headers=None, query_params=None, post_params=None,
   268               body=None, _preload_content=True, _request_timeout=None):
   269          return self.request("POST", url,
   270                              headers=headers,
   271                              query_params=query_params,
   272                              post_params=post_params,
   273                              _preload_content=_preload_content,
   274                              _request_timeout=_request_timeout,
   275                              body=body)
   276  
   277      def PUT(self, url, headers=None, query_params=None, post_params=None,
   278              body=None, _preload_content=True, _request_timeout=None):
   279          return self.request("PUT", url,
   280                              headers=headers,
   281                              query_params=query_params,
   282                              post_params=post_params,
   283                              _preload_content=_preload_content,
   284                              _request_timeout=_request_timeout,
   285                              body=body)
   286  
   287      def PATCH(self, url, headers=None, query_params=None, post_params=None,
   288                body=None, _preload_content=True, _request_timeout=None):
   289          return self.request("PATCH", url,
   290                              headers=headers,
   291                              query_params=query_params,
   292                              post_params=post_params,
   293                              _preload_content=_preload_content,
   294                              _request_timeout=_request_timeout,
   295                              body=body)
   296  
   297  
   298  class ApiException(Exception):
   299  
   300      def __init__(self, status=None, reason=None, http_resp=None):
   301          if http_resp:
   302              self.status = http_resp.status
   303              self.reason = http_resp.reason
   304              self.body = http_resp.data
   305              self.headers = http_resp.getheaders()
   306          else:
   307              self.status = status
   308              self.reason = reason
   309              self.body = None
   310              self.headers = None
   311  
   312      def __str__(self):
   313          """Custom error messages for exception"""
   314          error_message = "({0})\n"\
   315                          "Reason: {1}\n".format(self.status, self.reason)
   316          if self.headers:
   317              error_message += "HTTP response headers: {0}\n".format(
   318                  self.headers)
   319  
   320          if self.body:
   321              error_message += "HTTP response body: {0}\n".format(self.body)
   322  
   323          return error_message