From 0b484b0adfa78235d0a9a9deeac15ed3a437463e Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 9 Jul 2025 17:23:32 +0800 Subject: [PATCH] bugfix --- json/uapi.json | 24 +++++++++ json/uapiset.json | 2 +- json/upappapis.json | 20 ++++++++ json/upappkey.json | 5 +- uapi/appapi.py | 117 ++++++++++++++++++++++++-------------------- 5 files changed, 112 insertions(+), 56 deletions(-) diff --git a/json/uapi.json b/json/uapi.json index 9641754..5ba992d 100644 --- a/json/uapi.json +++ b/json/uapi.json @@ -1,6 +1,30 @@ { "tblname":"uapi", "params":{ + "toolbar":{ + "tools":[ + { + "selected_row":true, + "name":"test", + "icon":"{{entire_url('/imgs/test.svg')}}", + "label": "api测试" + } + ] + }, + "binds":[ + { + "wid":"self", + "event":"test", + "actiontype": "urlwidget", + "target":"PopupWindow", + "options":{ + "methid":"POST", + "params":{}, + "url":"{{entire_url('/uapi/uapi_test.ui')}}" + } + } + ], + "title":"API", "description":"API定义", "sortby":"name", diff --git a/json/uapiset.json b/json/uapiset.json index 00ded72..cc404f4 100644 --- a/json/uapiset.json +++ b/json/uapiset.json @@ -11,7 +11,7 @@ "editexclouded":["id"], "subtables":[ { - "field":"uapiid", + "field":"usid", "subtable": "uapi", "title": "API" } diff --git a/json/upappapis.json b/json/upappapis.json index 7e21308..cab250d 100644 --- a/json/upappapis.json +++ b/json/upappapis.json @@ -1,6 +1,26 @@ { "tblname":"upappapis", "params":{ + "toolbar":{ + "tools":[ + { + "name":"test", + "icon":"{{entire_url('/imgs/test.svg')}}", + "label": "测试", + "selected_row":true + } + ] + }, + "binds":[ + { + "wid":"self", + "event":"test", + "actiontype": "urlwidget", + "options":{ + "url":"{{entire_url('/uapi/apitest.dspy')}}" + } + } + ], "title":"使用api集", "description":"此系统使用的API集", "sortby":"name", diff --git a/json/upappkey.json b/json/upappkey.json index 3990028..c57b081 100644 --- a/json/upappkey.json +++ b/json/upappkey.json @@ -4,10 +4,9 @@ "title":"上位系统密码", "logined_userorgid":"ownerid", "description":"上位系统密码", - "sortby":"name", - "confidential_fields":["akikey", "userpwd" ], + "confidential_fields":["apikey", "apipasswd" ], "browserfields":{ - "exclouded":["id"], + "exclouded":["id", "ownerid"], "alters":{} }, "editexclouded":["id", "upappid", "ownerid"] diff --git a/uapi/appapi.py b/uapi/appapi.py index 5d97f12..ab6df9b 100644 --- a/uapi/appapi.py +++ b/uapi/appapi.py @@ -4,55 +4,68 @@ from traceback import format_exc from functools import partial from sqlor.dbpools import DBPools from appPublic.streamhttpclient import StreamHttpClient, liner +from appPublic.dictObject import DictObject +from appPublic.myTE import MyTemplateEngine from appPublic.log import debug, exception, error from ahserver.globalEnv import password_decode +from ahserver.serverenv import get_serverenv def get_dbname(): f = get_serverenv('get_module_dbname') dbname = f('uapi') return dbname -class UAPI(StreamHttpClient): - def __init__(self, appid, env={}): - self.appid = appid - super().__init__() +class UAPI: + def __init__(self, env={}): self.te = MyTemplateEngine([], env=env) self.env = env self.auth_api = None self.auth_ret = None - async def tmplrender(self, tmplstr, params={}): + async def rendertmpl(self, tmplstr, params={}): if tmplstr is None: return None ns = self.env.copy() ns.update(params) te = MyTemplateEngine([], env=self.env) - return te.renders(headerstmpl, ns) + return te.renders(tmplstr, ns) - async def make_call(self, request, upapiid, callerid, - params={}, - stream=False, - env={}): - self.env.update(env) + async def cvt_upappapi2uapi(self, upappapiid, callerid, params={}): + self.env.update(params) db = DBPools() dbname = get_dbname() uapi = None auth_uapi = None async with db.sqlorContext(dbname) as sor: - upapi = await self.get_upappapis(upapiid) - kinfo = await self.get_orgapikey(sor, upapi.upappid, callerid) + upappapi = await self.get_upappapis(sor, upappapiid) + kinfo = await self.get_orgapikey(sor, upappapi.upappid, callerid) self.env.update(kinfo) auth_uapi = None if kinfo.auth_apiid: - auth_upapi = await self.get_upappapis(kinfo.auth_apiid) + auth_upapi = await self.get_upappapis(sor, kinfo.auth_apiid) auth_uapi = await self.get_uapi(sor, kinfo.auth_upapi.uapiid) - uapi = await self.get_uapi(sor, upapi.uapiid) + uapi = await self.get_uapi(sor, upappapi.uapiid) + return auth_uapi, uapi + return None, None + + async def __call__(self, upapiid, callerid, params={}): + """ + """ + auth_uapi, uapi = await self.cvt_upappapi2uapi(upapiid, + callerid, params=params) + if uapi is None: + return if auth_uapi: await self.do_auth(auth_uapi) - if stream: - return await self.do_stream_call(self, request, uapi, params=params) - else: - return await self.do_call(self, request, uapi, params=params) + async for line in self.stream_gen(uapi): + yield line + + async def request(self, upapiid, callerid, params={}): + auth_uapi, uapi = await self.cvt_upappapi2uapi(upapiid, + callerid, params=params) + if auth_uapi: + await self.do_auth(auth_uapi) + return await self.do_call(uapi) async def do_auth(self, auth_uapi): b = await self.do_call(auth_uapi) @@ -60,65 +73,65 @@ class UAPI(StreamHttpClient): self.env.update(d) return - async def do_call(self, request, api, params={}): + async def do_call(self, api, params={}): url = self.env.get('baseurl') + api.path - method = auth_uapi.httpmethod - header = self.rendertmpl(api.headers, params=params) + method = api.httpmethod + header = await self.rendertmpl(api.headers) header = json.loads(headers) - body = self.rendertmpl(api.body, params=params) - _params = self.rendertmpl(api.params, params=params) + body = await self.rendertmpl(api.body) + _params = await self.rendertmpl(api.params) if _params: _params = json.loads(_params) - b = await self.request(method, url, + shc = StreamHttpClient() + b = await shc.request(method, url, headers=headers, - body=body, + data=body, params=_params) d = json.loads(b.encode('utf-8')) if api.response: - return self.rendertmpl(api.response, params=d) + return await self.rendertmpl(api.response, params=d) return d - async def do_stream_call(self, request, api, params={}): - self.resp = web.StreamResponse() - await self.resp.prepare(request) + async def stream_gen(self, api, params={}): url = self.env.get('baseurl') + api.path - method = auth_uapi.httpmethod - header = self.rendertmpl(api.headers, params=params) - header = json.loads(headers) - body = self.rendertmpl(api.body, params=params) + method = api.httpmethod + headers = await self.rendertmpl(api.headers) + headers = json.loads(headers) + body = await self.rendertmpl(api.body) if body: bdy = json.loads(body) bdy['stream'] = True body = bdy.dumps(bdy, ensure_ascii=False) - _params = self.rendertmpl(api.params, params=params) + _params = await self.rendertmpl(api.params) if _params: _params = json.loads(_params) - hc = StreamHttpClient() - gen = hc(method, url, + shc = StreamHttpClient() + gen = shc(method, url, headers=headers, - body=body, + data=body, params=_params) - self.chunk_match = self.api.chunk_match or '' + chunk_match = api.chunk_match or '' + cmlen = len(chunk_match) async for line in liner(gen): - self.streamline_handle(line) - return self.resp + if line.startswith(chunk_match): + cvt_line = self.streamline_handle(line[cmlen:], + api.streamresponse) + if cvt_line is not None: + yield cvt_line async def streamline_handle(self, line, resptmpl): - cnt = len(self.chunk_match) - line = line[cnt:] try: dic = json.loads(line) if resptmpl: - jstr = self.rendertmpl(resptmpl, dic) + '\n' + jstr = await self.rendertmpl(resptmpl, params=dic) + jstr += '\n' else: jstr = json.dumps(self.resp_json, ensure_ascii=False) + '\n' - bin = jstr.encode('utf-8') - await self.resp.write(bin) - await self.resp.drain() + return jstr except Exception as e: exception(f'{line=}\n{e=},{format_exc()}') - return + return None async def get_upappapis(self, sor, upapiid): recs = await sor.R('upappapis', {'id': upapiid}) @@ -150,7 +163,7 @@ a.myappid, a.apisetid, a.auth_apiid, a.baseurl, -b.*, +b.* from upapp a, upappkey b where a.id = b.upappid and a.id = ${appid}$ @@ -161,13 +174,13 @@ where a.id = b.upappid exception(f'{e}, {format_exc()}') raise e r = recs[0] - return { + return DictObject(**{ 'apikey':r.apikey, 'secretkey':r.secretkey, 'apisetid': r.apisetid, - 'auth_apiid': r.auth.apiid, + 'auth_apiid': r.auth_apiid, 'myappid': r.myappid - } + }) async def get_authapi(self, sor): sql = "select * from jsonhttpapi where name = 'auth' and appid=${appid}$"