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)