bugfix
This commit is contained in:
parent
c8ff8f551e
commit
5447713c3a
@ -3,66 +3,107 @@ from appPublic.httpclient import HttpClient, RESPONSE_TEXT, RESPONSE_JSON, RESPO
|
|||||||
from appPublic.argsConvert import ArgsConvert
|
from appPublic.argsConvert import ArgsConvert
|
||||||
|
|
||||||
class OAuthClient:
|
class OAuthClient:
|
||||||
def __init__(self, desc, chunk_handle=None):
|
"""
|
||||||
|
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')
|
assert desc.get('data')
|
||||||
assert desc.get('mapis')
|
|
||||||
self.desc = desc
|
self.desc = desc
|
||||||
self.data = desc.get('data')
|
self.data = desc.get('data')
|
||||||
self.mapis = desc.get('mapis')
|
self.converters = converters
|
||||||
self.mkeys = self.mapis.keys()
|
|
||||||
self._chunk_handle = chunk_handle
|
|
||||||
self.ac = ArgsConvert('${', '}')
|
self.ac = ArgsConvert('${', '}')
|
||||||
|
|
||||||
def stream_handle(self, chunk):
|
def setup_req_datas(self, data=[], ns={}):
|
||||||
if self._chunk_handle:
|
d = {}
|
||||||
self._chunk_handle(chunk)
|
for h in headers:
|
||||||
else:
|
d1 = self.setup_req_data(h, ns)
|
||||||
self.chunk_data = self.chunk_data + chunk
|
d.update(d1)
|
||||||
|
if d == {}:
|
||||||
|
return None
|
||||||
|
return d
|
||||||
|
|
||||||
|
def setup_req_data(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, mapi, params):
|
async def __call__(self, mapi, params):
|
||||||
self.chunk_data = ''
|
if not self.desc.get(mapi):
|
||||||
if mapi not in self.mkeys:
|
|
||||||
raise Exception(f'{mapi} not defined')
|
raise Exception(f'{mapi} not defined')
|
||||||
d = self.mapis[mapi]
|
self.api = self.desc[mapi]
|
||||||
|
if not self.api:
|
||||||
|
return {
|
||||||
|
"status":"error",
|
||||||
|
"code":'9999',
|
||||||
|
"message":f"{mapi} not defined"
|
||||||
|
}
|
||||||
assert d.get('url')
|
assert d.get('url')
|
||||||
method = d.get('method', 'GET')
|
method = d.get('method', 'GET')
|
||||||
headers = {}
|
myheaders = self.setup_req_data(self.api.headers, params)
|
||||||
for h in d.get('headers',{}):
|
myparams = self.setup_req_data(self.api.params, params)
|
||||||
headers[h.get('name')] = h.get('value')
|
mydata = self.setup_req_data(self.api.data, params)
|
||||||
mydata = {}
|
url = self.api.get('url')
|
||||||
for p in d.get('data', {}):
|
response_type = RESPONSE_JSON
|
||||||
mydata[p.get('name')] = p.get('value')
|
|
||||||
myparams = {}
|
|
||||||
for p in d.get('params', {}):
|
|
||||||
myparams[p.get('name')] = p.get('value')
|
|
||||||
url = d.get('url')
|
|
||||||
_params = self.datalize(myparams, params)
|
|
||||||
_headers = self.datalize(headers, params)
|
|
||||||
_data = self.datalize(mydata, params)
|
|
||||||
response_type = RESPONSE_STREAM
|
|
||||||
hc = HttpClient()
|
hc = HttpClient()
|
||||||
print(f'{url=}, {method=}, {_params=}, {_data=}, {_headers=}')
|
print(f'{url=}, {method=}, {myparams=}, {mydata=}, {myheaders=}')
|
||||||
resp_data = await hc.request(url, method, response_type=response_type,
|
resp_data = await hc.request(url, method, response_type=response_type,
|
||||||
params=_params,
|
params=None if myparams is None else myparams,
|
||||||
data=None if _data == {} else json.dumps(_data),
|
data=None if mydata is None else json.dumps(mydata),
|
||||||
stream_func=self.stream_handle,
|
headers=myheaders)
|
||||||
headers=_headers)
|
|
||||||
if not self._chunk_handle:
|
|
||||||
resp_data = self.chunk_data
|
|
||||||
if resp_data is None:
|
if resp_data is None:
|
||||||
raise Exception(f'request error:{url=}\n{method=}\n{response_type=}\n{_params=}\n{_headers=}')
|
return {
|
||||||
errfield = d.get('error_field')
|
"status":"error",
|
||||||
err = resp_data.get(errfield)
|
"code":None
|
||||||
|
"message":"https error"
|
||||||
|
}
|
||||||
|
err = self.check_if_error(resp_data)
|
||||||
if err:
|
if err:
|
||||||
msg = resp_data.get(d.get('error_msg_field'))
|
return err
|
||||||
raise Exception(f'Error:{url}\n{msg}')
|
return self.setup_return_data(resp_data)
|
||||||
|
|
||||||
respdesc= d.get('resp_set_data', [])
|
|
||||||
for r in respdesc:
|
|
||||||
v = resp_data[r['field']]
|
|
||||||
k = r['name']
|
|
||||||
self.data[k] = v
|
|
||||||
return resp_data
|
|
||||||
|
|
||||||
def datalize(self, dic, data={}):
|
def datalize(self, dic, data={}):
|
||||||
mydata = self.data.copy()
|
mydata = self.data.copy()
|
||||||
@ -70,10 +111,51 @@ class OAuthClient:
|
|||||||
s1 = self.ac.convert(dic, mydata)
|
s1 = self.ac.convert(dic, mydata)
|
||||||
return s1
|
return s1
|
||||||
|
|
||||||
def is_error(self, resp_data, error_field):
|
def get_resp_data(self, resp, keys, converter=None):
|
||||||
if resp_data.get(error_feield):
|
d = resp.get_dic_data_by_keys(desc.keys)
|
||||||
return True
|
if converter:
|
||||||
|
f = self.converters.get(converter)
|
||||||
|
if f:
|
||||||
|
d = f(d)
|
||||||
|
return d
|
||||||
|
|
||||||
|
def setup_return_data(self, resp):
|
||||||
|
data = {}
|
||||||
|
for desc in self.api.resp:
|
||||||
|
k = desc.name
|
||||||
|
v = self.get_resp_data(resp, desc.keys, desc.converter)
|
||||||
|
data[k] = v
|
||||||
|
return {
|
||||||
|
"status":"ok",
|
||||||
|
"data":data
|
||||||
|
}
|
||||||
|
|
||||||
|
def check_if_error(self, resp, error_field):
|
||||||
|
if not self.api.error_if:
|
||||||
|
return None
|
||||||
|
ei = self.api.error_if
|
||||||
|
v = resp.get_dic_data_by_keys(ei.keys)
|
||||||
|
v1 = ei.value
|
||||||
|
if ei.converter:
|
||||||
|
f = self.converters.get(ei.converter)
|
||||||
|
if f:
|
||||||
|
v = f(v)
|
||||||
|
if not ei.op:
|
||||||
|
ei.op = '=='
|
||||||
|
if ei.op in ['==', '='] and v == v1 or ei.op == '!=' and v != v1:
|
||||||
|
code = None
|
||||||
|
message = None
|
||||||
|
if ei.code_keys:
|
||||||
|
code = resp.get_dic_data_by_keys(ei.code_keys)
|
||||||
|
if ei.msg_keys:
|
||||||
|
message = resp.get_dic_data_by_keys(ei.msg_keys)
|
||||||
|
return {
|
||||||
|
"status":"error",
|
||||||
|
"code:code,
|
||||||
|
"message":message
|
||||||
|
}
|
||||||
|
return None
|
||||||
|
|
||||||
def set_data(self, resp_data, data_desc):
|
def set_data(self, resp_data, data_desc):
|
||||||
for dd in data_desc:
|
for dd in data_desc:
|
||||||
f = dd['field']
|
f = dd['field']
|
||||||
|
Loading…
Reference in New Issue
Block a user