github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/clients/python/lakefs_sdk/rest.py (about)

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