bugfix
This commit is contained in:
parent
66f16d3e87
commit
54109828b6
13
json/uapi.json
Normal file
13
json/uapi.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"tblname":"uapi",
|
||||
"params":{
|
||||
"title":"API",
|
||||
"description":"API定义",
|
||||
"sortby":"name",
|
||||
"browserfields":{
|
||||
"exclouded":["id"],
|
||||
"alters":{}
|
||||
},
|
||||
"editexclouded":["id", "usid"]
|
||||
}
|
||||
}
|
@ -8,6 +8,13 @@
|
||||
"exclouded":["id"],
|
||||
"alters":{}
|
||||
},
|
||||
"editexclouded":["id"]
|
||||
"editexclouded":["id"],
|
||||
"subtables":[
|
||||
{
|
||||
"field":"uapiid",
|
||||
"subtable": "uapi",
|
||||
"title": "API"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,18 @@
|
||||
"exclouded":["id"],
|
||||
"alters":{}
|
||||
},
|
||||
"editexclouded":["id"]
|
||||
"editexclouded":["id"],
|
||||
"subtables":[
|
||||
{
|
||||
"field":"upappid",
|
||||
"subtable": "upappapis",
|
||||
"title": "API集"
|
||||
},
|
||||
{
|
||||
"field":"upappid",
|
||||
"subtable": "upappkey",
|
||||
"title": "APIKEY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,6 @@
|
||||
"exclouded":["id"],
|
||||
"alters":{}
|
||||
},
|
||||
"editexclouded":["id"]
|
||||
"editexclouded":["id", "upappid"]
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
"tblname":"upappkey",
|
||||
"params":{
|
||||
"title":"上位系统密码",
|
||||
"logined_userorgid":"ownerid",
|
||||
"description":"上位系统密码",
|
||||
"sortby":"name",
|
||||
"confidential_fields":["akikey", "userpwd" ],
|
||||
@ -9,6 +10,6 @@
|
||||
"exclouded":["id"],
|
||||
"alters":{}
|
||||
},
|
||||
"editexclouded":["id"]
|
||||
"editexclouded":["id", "upappid", "ownerid"]
|
||||
}
|
||||
}
|
||||
|
BIN
models/uapi.xlsx
BIN
models/uapi.xlsx
Binary file not shown.
Binary file not shown.
52
setup.py
52
setup.py
@ -1,52 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from uapi.version import __version__
|
||||
try:
|
||||
from setuptools import setup
|
||||
except ImportError:
|
||||
from distutils.core import setup
|
||||
required = []
|
||||
with open('requirements.txt', 'r') as f:
|
||||
ls = f.read()
|
||||
required = ls.split('\n')
|
||||
|
||||
with open('uapi/version.py', 'r') as f:
|
||||
x = f.read()
|
||||
y = x[x.index("'")+1:]
|
||||
z = y[:y.index("'")]
|
||||
version = z
|
||||
with open("README.md", "r") as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
name = "uapi"
|
||||
description = "uapi"
|
||||
author = "yumoqing"
|
||||
email = "yumoqing@gmail.com"
|
||||
|
||||
package_data = {}
|
||||
|
||||
setup(
|
||||
name="uapi",
|
||||
version=version,
|
||||
|
||||
# uncomment the following lines if you fill them out in release.py
|
||||
description=description,
|
||||
author=author,
|
||||
author_email=email,
|
||||
platforms='any',
|
||||
install_requires=required ,
|
||||
packages=[
|
||||
"uapi"
|
||||
],
|
||||
package_data=package_data,
|
||||
keywords = [
|
||||
],
|
||||
url="https://github.com/yumoqing/uapi",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
classifiers = [
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python :: 3',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
],
|
||||
)
|
@ -1 +0,0 @@
|
||||
from .version import __version__
|
244
uapi/appapi.py
244
uapi/appapi.py
@ -1,17 +1,174 @@
|
||||
import json
|
||||
|
||||
from traceback import format_exc
|
||||
from functools import partial
|
||||
from sqlor.dbpools import DBPools
|
||||
from appPublic.httpclient import JsonHttpAPI
|
||||
from appPublic.log import debug, exception,
|
||||
from appPublic.streamhttpclient import StreamHttpClient, liner
|
||||
from appPublic.log import debug, exception, error
|
||||
from ahserver.globalEnv import password_decode
|
||||
from aiohttp import web
|
||||
|
||||
class AppAPI(JsonHttpAPI):
|
||||
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__(env=env)
|
||||
super().__init__()
|
||||
self.te = MyTemplateEngine([], env=env)
|
||||
self.env = env
|
||||
self.auth_api = None
|
||||
self.auth_ret = None
|
||||
|
||||
async def tmplrender(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)
|
||||
|
||||
async def make_call(self, request, upapiid, callerid,
|
||||
params={},
|
||||
stream=False,
|
||||
env={}):
|
||||
self.env.update(env)
|
||||
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)
|
||||
self.env.update(kinfo)
|
||||
auth_uapi = None
|
||||
if kinfo.auth_apiid:
|
||||
auth_upapi = await self.get_upappapis(kinfo.auth_apiid)
|
||||
auth_uapi = await self.get_uapi(sor, kinfo.auth_upapi.uapiid)
|
||||
uapi = await self.get_uapi(sor, upapi.uapiid)
|
||||
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 def do_auth(self, auth_uapi):
|
||||
b = await self.do_call(auth_uapi)
|
||||
d = json.loads(b.encode('utf-8'))
|
||||
self.env.update(d)
|
||||
return
|
||||
|
||||
async def do_call(self, request, 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)
|
||||
_params = self.rendertmpl(api.params, params=params)
|
||||
if _params:
|
||||
_params = json.loads(_params)
|
||||
b = await self.request(method, url,
|
||||
headers=headers,
|
||||
body=body,
|
||||
params=_params)
|
||||
|
||||
d = json.loads(b.encode('utf-8'))
|
||||
if api.response:
|
||||
return 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)
|
||||
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)
|
||||
if body:
|
||||
bdy = json.loads(body)
|
||||
bdy['stream'] = True
|
||||
body = bdy.dumps(bdy, ensure_ascii=False)
|
||||
_params = self.rendertmpl(api.params, params=params)
|
||||
if _params:
|
||||
_params = json.loads(_params)
|
||||
hc = StreamHttpClient()
|
||||
gen = hc(method, url,
|
||||
headers=headers,
|
||||
body=body,
|
||||
params=_params)
|
||||
self.chunk_match = self.api.chunk_match or ''
|
||||
async for line in liner(gen):
|
||||
self.streamline_handle(line)
|
||||
return self.resp
|
||||
|
||||
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'
|
||||
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()
|
||||
except Exception as e:
|
||||
exception(f'{line=}\n{e=},{format_exc()}')
|
||||
return
|
||||
|
||||
async def get_upappapis(self, sor, upapiid):
|
||||
recs = await sor.R('upappapis', {'id': upapiid})
|
||||
if len(recs) < 1:
|
||||
e = Exception(f'{upapiid} not found in table(upappapis)')
|
||||
exception(f'{e}\n{format_exc()}')
|
||||
raise e
|
||||
return recs[0]
|
||||
|
||||
async def get_uapi(self, sor, uapiid):
|
||||
recs = await sor.R('uapi', {'id': uapiid})
|
||||
if len(recs) < 1:
|
||||
e = Exception(f'{uapiid} not found in table(uapi)')
|
||||
exception(f'{e}\n{format_exc()}')
|
||||
raise e
|
||||
return recs[0]
|
||||
|
||||
async def get_orgapikey(self, sor, upappid, callerid):
|
||||
"""
|
||||
argumemts:
|
||||
upappid: upappid which will make call to
|
||||
orgid: owner organization or user which as the caller of the call
|
||||
return:
|
||||
None: this orgid has not gotton apikey from upapp
|
||||
dict if apikey and upapp infos
|
||||
"""
|
||||
sql = """select
|
||||
a.myappid,
|
||||
a.apisetid,
|
||||
a.auth_apiid,
|
||||
a.baseurl,
|
||||
b.*,
|
||||
from upapp a, upappkey b
|
||||
where a.id = b.upappid
|
||||
and a.id = ${appid}$
|
||||
and b.ownerid = ${orgid}$"""
|
||||
recs = await sor.sqlExe(sql, {'appid':upappid, 'orgid': callerid})
|
||||
if len(recs) < 1:
|
||||
e = Exception(f'{appid=}, {callerid=} has not apikey')
|
||||
exception(f'{e}, {format_exc()}')
|
||||
raise e
|
||||
r = recs[0]
|
||||
return {
|
||||
'apikey':r.apikey,
|
||||
'secretkey':r.secretkey,
|
||||
'apisetid': r.apisetid,
|
||||
'auth_apiid': r.auth.apiid,
|
||||
'myappid': r.myappid
|
||||
}
|
||||
|
||||
async def get_authapi(self, sor):
|
||||
sql = "select * from jsonhttpapi where name = 'auth' and appid=${appid}$"
|
||||
recs = await sor.sqlExe(sql, {'appid': self.appid})
|
||||
@ -59,80 +216,3 @@ where
|
||||
return recs[0]
|
||||
return None
|
||||
|
||||
async def request(self, apiname, ns):
|
||||
orgs = ns.get('orgs')
|
||||
api = await self.get_apiinfo(orgs, apiname)
|
||||
if api is None:
|
||||
e = Exception(f'{self.appid} app has not {apiname} api')
|
||||
exception(f'{e=}, {format_exc()}')
|
||||
raise e
|
||||
ns1 = self.env.copy()
|
||||
ns1['apikey'] = api.apikey
|
||||
ns1['secretkey'] = api.secretkey
|
||||
ns1.update(ns)
|
||||
if api.need_auth:
|
||||
if self.auth_ret is None:
|
||||
auth_url = api.baseurl + self.auth_api.path
|
||||
self.auth_ret = await self.call(auth_url,
|
||||
method=self.auth_api.httpmethod,
|
||||
ns=ns1,
|
||||
headerstmpl=self.auth_api.headers,
|
||||
paramstmpl=self.auth_api.params,
|
||||
datatmpl=self.auth_api.data,
|
||||
resptmpl=self.auth_api.response)
|
||||
if self.auth_ret is None:
|
||||
e = Exception(f'{self.appid} app auth error')
|
||||
exception(f'{e=}, {format_exc()}')
|
||||
raise e
|
||||
ns1.update(self.auth_ret)
|
||||
stream_func = None
|
||||
if api.stream:
|
||||
await self.stream_begin()
|
||||
stream_func = partial(self.stream_func, api, ns1)
|
||||
url = api.baseurl + api.path
|
||||
ret = await self.call(url, method=api.httpmethod, ns=ns1,
|
||||
stream_func = stream_func,
|
||||
headerstmpl=api.headers,
|
||||
paramstmpl=api.params,
|
||||
datatmpl=api.data,
|
||||
resptmpl=api.response)
|
||||
if api.stream:
|
||||
return await self.stream_end()
|
||||
return ret
|
||||
|
||||
async def stream_begin(self):
|
||||
pass
|
||||
|
||||
async def stream_end(self):
|
||||
return None
|
||||
|
||||
async def stream_func(self, api, ns, chunk):
|
||||
if api.chunk_match:
|
||||
chunk = chunk[len(api.chunk_match):]
|
||||
d = chunk
|
||||
if api.streamresponse:
|
||||
d = json.loads(chunk)
|
||||
ns1 = ns.copy()
|
||||
ns1.update(d)
|
||||
d = self.te.renders(api.streamresponse, ns1)
|
||||
return d
|
||||
|
||||
|
||||
class AiohttpAppAPI(AppAPI):
|
||||
async def request(self, request, apiname, ns):
|
||||
self.request = request
|
||||
return await super().request(apiname, ns)
|
||||
|
||||
async def stream_begin(self):
|
||||
self.resp = web.StreamResponse()
|
||||
await self.resp.prepare(request)
|
||||
|
||||
async def stream_end(self):
|
||||
return self.resp
|
||||
|
||||
async def stream_func(self, api, ns, chunk):
|
||||
d = super().stream_func(api, ns, chuck)
|
||||
b = d.encode('utf-8')
|
||||
await self.resp.write(bin)
|
||||
await self.resp.drain()
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
from ahserver.serverenv import ServerEnv
|
||||
from .appapi import AppAPI, AiohttpAppAPI
|
||||
from .appapi import UAPI
|
||||
|
||||
def load_uapi():
|
||||
g = ServerEnv()
|
||||
g.AiohttpAppAPI = AiohttpAppAPI
|
||||
g.AppAPI = AppAPI
|
||||
g.UAPI = UAPI
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
__version__ = '0.0.1'
|
Loading…
Reference in New Issue
Block a user