github.com/phrase/openapi@v0.0.0-20240514140800-49e8a106740e/openapi-generator/templates/python/asyncio/rest.mustache (about) 1 # coding: utf-8 2 3 {{>partial_header}} 4 5 import io 6 import json 7 import logging 8 import re 9 import ssl 10 11 import aiohttp 12 import certifi 13 # python 2 and python 3 compatibility library 14 from six.moves.urllib.parse import urlencode 15 16 from {{packageName}}.exceptions import ApiException, ApiValueError 17 18 logger = logging.getLogger(__name__) 19 20 21 class RESTResponse(io.IOBase): 22 23 def __init__(self, resp, data): 24 self.aiohttp_response = resp 25 self.status = resp.status 26 self.reason = resp.reason 27 self.data = data 28 29 def getheaders(self): 30 """Returns a CIMultiDictProxy of the response headers.""" 31 return self.aiohttp_response.headers 32 33 def getheader(self, name, default=None): 34 """Returns a given response header.""" 35 return self.aiohttp_response.headers.get(name, default) 36 37 38 class RESTClientObject(object): 39 40 def __init__(self, configuration, pools_size=4, maxsize=None): 41 42 # maxsize is number of requests to host that are allowed in parallel 43 if maxsize is None: 44 maxsize = configuration.connection_pool_maxsize 45 46 # ca_certs 47 if configuration.ssl_ca_cert: 48 ca_certs = configuration.ssl_ca_cert 49 else: 50 # if not set certificate file, use Mozilla's root certificates. 51 ca_certs = certifi.where() 52 53 ssl_context = ssl.create_default_context(cafile=ca_certs) 54 if configuration.cert_file: 55 ssl_context.load_cert_chain( 56 configuration.cert_file, keyfile=configuration.key_file 57 ) 58 59 if not configuration.verify_ssl: 60 ssl_context.check_hostname = False 61 ssl_context.verify_mode = ssl.CERT_NONE 62 63 connector = aiohttp.TCPConnector( 64 limit=maxsize, 65 ssl=ssl_context 66 ) 67 68 self.proxy = configuration.proxy 69 self.proxy_headers = configuration.proxy_headers 70 71 # https pool manager 72 self.pool_manager = aiohttp.ClientSession( 73 connector=connector 74 ) 75 76 async def close(self): 77 await self.pool_manager.close() 78 79 async def request(self, method, url, query_params=None, headers=None, 80 body=None, post_params=None, _preload_content=True, 81 _request_timeout=None): 82 """Execute request 83 84 :param method: http request method 85 :param url: http request url 86 :param query_params: query parameters in the url 87 :param headers: http request headers 88 :param body: request json body, for `application/json` 89 :param post_params: request post parameters, 90 `application/x-www-form-urlencoded` 91 and `multipart/form-data` 92 :param _preload_content: this is a non-applicable field for 93 the AiohttpClient. 94 :param _request_timeout: timeout setting for this request. If one 95 number provided, it will be total request 96 timeout. It can also be a pair (tuple) of 97 (connection, read) timeouts. 98 """ 99 method = method.upper() 100 assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', 101 'PATCH', 'OPTIONS'] 102 103 if post_params and body: 104 raise ApiValueError( 105 "body parameter cannot be used with post_params parameter." 106 ) 107 108 post_params = post_params or {} 109 headers = headers or {} 110 timeout = _request_timeout or 5 * 60 111 112 if 'Content-Type' not in headers: 113 headers['Content-Type'] = 'application/json' 114 115 args = { 116 "method": method, 117 "url": url, 118 "timeout": timeout, 119 "headers": headers 120 } 121 122 if self.proxy: 123 args["proxy"] = self.proxy 124 if self.proxy_headers: 125 args["proxy_headers"] = self.proxy_headers 126 127 if query_params: 128 args["url"] += '?' + urlencode(query_params) 129 130 # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` 131 if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: 132 if re.search('json', headers['Content-Type'], re.IGNORECASE): 133 if body is not None: 134 body = json.dumps(body) 135 args["data"] = body 136 elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501 137 args["data"] = aiohttp.FormData(post_params) 138 elif headers['Content-Type'] == 'multipart/form-data': 139 # must del headers['Content-Type'], or the correct 140 # Content-Type which generated by aiohttp 141 del headers['Content-Type'] 142 data = aiohttp.FormData() 143 for param in post_params: 144 k, v = param 145 if isinstance(v, tuple) and len(v) == 3: 146 data.add_field(k, 147 value=v[1], 148 filename=v[0], 149 content_type=v[2]) 150 else: 151 data.add_field(k, v) 152 args["data"] = data 153 154 # Pass a `bytes` parameter directly in the body to support 155 # other content types than Json when `body` argument is provided 156 # in serialized form 157 elif isinstance(body, bytes): 158 args["data"] = body 159 else: 160 # Cannot generate the request from given parameters 161 msg = """Cannot prepare a request message for provided 162 arguments. Please check that your arguments match 163 declared content type.""" 164 raise ApiException(status=0, reason=msg) 165 166 r = await self.pool_manager.request(**args) 167 if _preload_content: 168 169 data = await r.text() 170 r = RESTResponse(r, data) 171 172 # log response body 173 logger.debug("response body: %s", r.data) 174 175 if not 200 <= r.status <= 299: 176 raise ApiException(http_resp=r) 177 178 return r 179 180 async def GET(self, url, headers=None, query_params=None, 181 _preload_content=True, _request_timeout=None): 182 return (await self.request("GET", url, 183 headers=headers, 184 _preload_content=_preload_content, 185 _request_timeout=_request_timeout, 186 query_params=query_params)) 187 188 async def HEAD(self, url, headers=None, query_params=None, 189 _preload_content=True, _request_timeout=None): 190 return (await self.request("HEAD", url, 191 headers=headers, 192 _preload_content=_preload_content, 193 _request_timeout=_request_timeout, 194 query_params=query_params)) 195 196 async def OPTIONS(self, url, headers=None, query_params=None, 197 post_params=None, body=None, _preload_content=True, 198 _request_timeout=None): 199 return (await self.request("OPTIONS", url, 200 headers=headers, 201 query_params=query_params, 202 post_params=post_params, 203 _preload_content=_preload_content, 204 _request_timeout=_request_timeout, 205 body=body)) 206 207 async def DELETE(self, url, headers=None, query_params=None, body=None, 208 _preload_content=True, _request_timeout=None): 209 return (await self.request("DELETE", url, 210 headers=headers, 211 query_params=query_params, 212 _preload_content=_preload_content, 213 _request_timeout=_request_timeout, 214 body=body)) 215 216 async def POST(self, url, headers=None, query_params=None, 217 post_params=None, body=None, _preload_content=True, 218 _request_timeout=None): 219 return (await self.request("POST", url, 220 headers=headers, 221 query_params=query_params, 222 post_params=post_params, 223 _preload_content=_preload_content, 224 _request_timeout=_request_timeout, 225 body=body)) 226 227 async def PUT(self, url, headers=None, query_params=None, post_params=None, 228 body=None, _preload_content=True, _request_timeout=None): 229 return (await self.request("PUT", url, 230 headers=headers, 231 query_params=query_params, 232 post_params=post_params, 233 _preload_content=_preload_content, 234 _request_timeout=_request_timeout, 235 body=body)) 236 237 async def PATCH(self, url, headers=None, query_params=None, 238 post_params=None, body=None, _preload_content=True, 239 _request_timeout=None): 240 return (await self.request("PATCH", url, 241 headers=headers, 242 query_params=query_params, 243 post_params=post_params, 244 _preload_content=_preload_content, 245 _request_timeout=_request_timeout, 246 body=body))