apppublic/build/lib/appPublic/oauth_client.py
2024-09-23 14:12:00 +08:00

189 lines
4.5 KiB
Python

import json
from appPublic.httpclient import HttpClient, RESPONSE_TEXT, RESPONSE_JSON, RESPONSE_BIN,RESPONSE_FILE, RESPONSE_STREAM, HttpError
from appPublic.argsConvert import ArgsConvert
from appPublic.dictObject import DictObject
class OAuthClient:
"""
OauthClient is a http(s) client for request a api annouce by other
it send https request and get back a json data
we can check the response json data to check if the call is success or failed
desc has the following format
{
"data": predefined data, and if nessory, you can add to new data to it
"method_name":{
"url"
"method",
"headers",
"params":arguments will appended to url with ?a=a&b=b...
"data":data will send in the request body, json format
"resp":[
{
"name":
"converter":default none, if not, convert response data first before set the returen data
"keys":resposne json data keys to achieve data
}
]
"error_if":{
"keys":
"op",
"value"
}
}
}
return:
if error:
return {
"status":"error",
"code":code returned by server
"message":"message returned by server
}
else:
return {
"status":"ok",
"data":...
}
"""
def __init__(self, desc, converters={}):
assert desc.get('data')
self.desc = desc
self.data = desc.get('data')
self.converters = converters
self.ac = ArgsConvert('${', '}')
def setup_req_data(self, data=[], ns={}):
d = {}
if data is None:
return None
for h in data:
d1 = self.setup_req_kv(h, ns)
d.update(d1)
if d == {}:
return None
return d
def setup_req_kv(self, d, ns):
rd = {
d.name:d.value
}
nd = self.datalize(rd, ns)
if d.converter:
f = self.converters.get(d.converter)
if f:
nd[d.name] = f(nd.get(d.name))
return nd
async def __call__(self, host, mapi, params):
if not self.desc.get(mapi):
raise Exception(f'{mapi} not defined')
self.api = self.desc[mapi]
if not self.api:
return {
"status":"error",
"code":'9999',
"message":f"{mapi} not defined"
}
path = self.datalize(self.api.path, params)
url = host + path
method = self.api.get('method', 'GET')
myheaders = self.setup_req_data(self.api.headers, params)
myparams = self.setup_req_data(self.api.params, params)
mydata = self.setup_req_data(self.api.data, params)
response_type = RESPONSE_JSON
hc = HttpClient()
print(f'{url=}, {method=}, {myparams=}, {mydata=}, {myheaders=}')
resp_data = None
try:
resp_data = await hc.request(url, method, response_type=response_type,
params=None if not myparams else myparams,
data=None if not mydata else mydata,
headers=myheaders)
resp_data = DictObject(**resp_data)
print(resp_data)
except HttpError as e:
return {
"status":"error",
"code":e.code,
"message":e.msg
}
if resp_data is None:
return {
"status":"error",
"code":None,
"message":"https error"
}
err = self.check_if_error(resp_data)
if err:
return err
return self.setup_return_data(resp_data)
def datalize(self, dic, data={}):
mydata = self.data.copy()
mydata.update(data)
s1 = self.ac.convert(dic, mydata)
return s1
def get_resp_data(self, resp, keys, converter=None):
d = resp.get_data_by_keys(keys)
if converter:
f = self.converters.get(converter)
if f:
d = f(d)
return d
def setup_return_data(self, resp):
data = {}
if not self.api.resp:
return {
'status':'ok',
'data':{}
}
for desc in self.api.resp:
k = desc.name
v = self.get_resp_data(resp, desc.resp_keys, desc.converter)
data[k] = v
return {
"status":"ok",
"data":data
}
def check_if_error(self, resp):
if not self.api.error_if:
return None
ei = self.api.error_if
v = resp.get_data_by_keys(ei.error_keys)
v1 = ei.value
if ei.converter:
f = self.converters.get(ei.converter)
if f:
v = f(v)
if not ei.op:
ei.op = '=='
print(f'{ei.keys=},{v=}, {v1=}, {ei.op=}{v==v1}, {resp.base_resp.status_code=}')
if (ei.op == '==' and v == v1) or (ei.op == '!=' and v != v1):
print(f'{v=}, {v1=}, {ei.op=}{v==v1}')
code = None
message = None
if ei.code_keys:
code = resp.get_data_by_keys(ei.code_keys)
if ei.msg_keys:
message = resp.get_data_by_keys(ei.msg_keys)
return {
"status":"error",
"code":code,
"message":message
}
print(f'check_if_error ok:{v=}, {v1=}, {ei.op=}{v==v1}')
return None
def set_data(self, resp_data, data_desc):
for dd in data_desc:
f = dd['field']
n = dd['name']
if resp_data.get(f):
self.data[n] = resp_data[f]