2019-07-10 17:34:45 +08:00
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import json
|
|
|
|
import codecs
|
2023-10-12 15:46:05 +08:00
|
|
|
import aiofiles
|
2019-07-10 17:34:45 +08:00
|
|
|
from aiohttp.web_request import Request
|
|
|
|
from aiohttp.web_response import Response, StreamResponse
|
|
|
|
|
|
|
|
from appPublic.jsonConfig import getConfig
|
|
|
|
from appPublic.dictObject import DictObject
|
|
|
|
from appPublic.folderUtils import listFile
|
2022-06-23 14:58:03 +08:00
|
|
|
from appPublic.app_logger import AppLogger
|
2019-07-10 17:34:45 +08:00
|
|
|
|
2020-12-18 13:27:53 +08:00
|
|
|
from .utils import unicode_escape
|
2019-07-10 17:34:45 +08:00
|
|
|
from .serverenv import ServerEnv
|
2023-12-18 22:15:24 +08:00
|
|
|
from .filetest import current_fileno
|
2019-07-10 17:34:45 +08:00
|
|
|
|
|
|
|
class ObjectCache:
|
|
|
|
def __init__(self):
|
|
|
|
self.cache = {}
|
|
|
|
|
|
|
|
def store(self,path,obj):
|
|
|
|
o = self.cache.get(path,None)
|
|
|
|
if o is not None:
|
|
|
|
try:
|
|
|
|
del o.cached_obj
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
o = DictObject()
|
|
|
|
o.cached_obj = obj
|
|
|
|
o.mtime = os.path.getmtime(path)
|
|
|
|
self.cache[path] = o
|
|
|
|
|
|
|
|
def get(self,path):
|
|
|
|
o = self.cache.get(path)
|
|
|
|
if o:
|
|
|
|
if os.path.getmtime(path) > o.mtime:
|
|
|
|
return None
|
|
|
|
return o.cached_obj
|
|
|
|
return None
|
|
|
|
|
2020-11-09 02:39:35 +08:00
|
|
|
|
2019-07-10 17:34:45 +08:00
|
|
|
|
2022-06-23 14:58:03 +08:00
|
|
|
class BaseProcessor(AppLogger):
|
2019-07-10 17:34:45 +08:00
|
|
|
@classmethod
|
|
|
|
def isMe(self,name):
|
|
|
|
return name=='base'
|
|
|
|
|
|
|
|
def __init__(self,path,resource):
|
2023-02-22 22:16:41 +08:00
|
|
|
super().__init__()
|
|
|
|
self.env_set = False
|
2019-07-10 17:34:45 +08:00
|
|
|
self.path = path
|
|
|
|
self.resource = resource
|
|
|
|
self.retResponse = None
|
2019-11-29 11:35:33 +08:00
|
|
|
# self.last_modified = os.path.getmtime(path)
|
|
|
|
# self.content_length = os.path.getsize(path)
|
2019-07-10 17:34:45 +08:00
|
|
|
self.headers = {
|
2019-11-29 11:35:33 +08:00
|
|
|
'Content-Type': 'text/html; utf-8',
|
2019-07-10 17:34:45 +08:00
|
|
|
'Accept-Ranges': 'bytes'
|
|
|
|
}
|
|
|
|
self.content = ''
|
|
|
|
|
2023-07-04 12:02:13 +08:00
|
|
|
async def be_call(self, request, params={}):
|
|
|
|
return await self.path_call(request, params=params)
|
|
|
|
|
2023-07-04 18:16:27 +08:00
|
|
|
async def set_run_env(self, request, params={}):
|
2023-02-22 22:16:41 +08:00
|
|
|
if self.env_set:
|
|
|
|
return
|
2024-02-19 14:00:27 +08:00
|
|
|
self.real_path = self.resource.url2file(request.path)
|
2019-11-28 15:24:09 +08:00
|
|
|
g = ServerEnv()
|
2019-11-29 18:01:58 +08:00
|
|
|
self.run_ns = {}
|
2019-11-28 15:24:09 +08:00
|
|
|
self.run_ns.update(g)
|
|
|
|
self.run_ns.update(self.resource.y_env)
|
2019-11-29 18:01:58 +08:00
|
|
|
self.run_ns['request'] = request
|
2021-01-25 12:03:19 +08:00
|
|
|
kw = await self.run_ns['request2ns']()
|
2023-07-04 18:16:27 +08:00
|
|
|
kw.update(params)
|
2021-01-25 12:03:19 +08:00
|
|
|
self.run_ns['params_kw'] = kw
|
|
|
|
self.run_ns.update(kw)
|
2022-01-03 11:53:39 +08:00
|
|
|
self.run_ns['ref_real_path'] = self.real_path
|
|
|
|
self.run_ns['processor'] = self
|
2023-02-22 22:16:41 +08:00
|
|
|
self.env_set = True
|
2020-12-19 14:00:04 +08:00
|
|
|
|
|
|
|
async def execute(self,request):
|
|
|
|
await self.set_run_env(request)
|
2019-07-10 17:34:45 +08:00
|
|
|
await self.datahandle(request)
|
2020-12-11 01:48:32 +08:00
|
|
|
return self.content
|
|
|
|
|
2023-06-08 12:06:38 +08:00
|
|
|
def set_response_headers(self, response):
|
2023-06-08 13:07:19 +08:00
|
|
|
response.headers['Access-Control-Expose-Headers'] = 'Set-Cookie'
|
|
|
|
# response.headers['Access-Control-Allow-Credentials'] = 'true'
|
|
|
|
# response.headers['Access-Control-Allow-Origin'] = '47.93.12.75'
|
2023-06-08 12:06:38 +08:00
|
|
|
|
2020-12-11 01:48:32 +08:00
|
|
|
async def handle(self,request):
|
|
|
|
await self.execute(request)
|
2023-08-05 16:41:27 +08:00
|
|
|
jsonflg = False
|
2019-07-10 17:34:45 +08:00
|
|
|
if self.retResponse is not None:
|
2023-06-08 12:06:38 +08:00
|
|
|
self.set_response_headers(self.retResponse)
|
2019-07-10 17:34:45 +08:00
|
|
|
return self.retResponse
|
2020-06-07 22:55:08 +08:00
|
|
|
elif type(self.content) == type({}) :
|
2023-08-05 16:41:27 +08:00
|
|
|
self.content = json.dumps(self.content, indent=4)
|
|
|
|
jsonflg = True
|
2020-06-07 22:55:08 +08:00
|
|
|
elif type(self.content) == type([]):
|
2023-08-05 16:41:27 +08:00
|
|
|
self.content = json.dumps(self.content, indent=4)
|
|
|
|
jsonflg = True
|
2024-02-20 18:04:58 +08:00
|
|
|
elif type(self.content) == type(b''):
|
|
|
|
self.headers['Access-Control-Expose-Headers'] = 'Set-Cookie'
|
|
|
|
resp = Response(body=self.content,headers=self.headers)
|
|
|
|
self.set_response_headers(resp)
|
|
|
|
return resp
|
2023-08-05 16:41:27 +08:00
|
|
|
else:
|
|
|
|
try:
|
|
|
|
json.loads(self.content)
|
|
|
|
jsonflg = True
|
|
|
|
except:
|
|
|
|
pass
|
2022-05-17 16:51:39 +08:00
|
|
|
|
2023-08-05 16:41:27 +08:00
|
|
|
if jsonflg:
|
|
|
|
self.headers['Content-Type'] = "application/json; utf-8"
|
|
|
|
|
2023-06-08 10:37:54 +08:00
|
|
|
self.headers['Access-Control-Expose-Headers'] = 'Set-Cookie'
|
2023-06-08 12:06:38 +08:00
|
|
|
resp = Response(text=self.content,headers=self.headers)
|
|
|
|
self.set_response_headers(resp)
|
|
|
|
return resp
|
2019-07-10 17:34:45 +08:00
|
|
|
|
2019-11-28 15:24:09 +08:00
|
|
|
async def datahandle(self,request):
|
2022-06-23 14:58:03 +08:00
|
|
|
self.debug('*******Error*************')
|
2019-07-10 17:34:45 +08:00
|
|
|
self.content=''
|
|
|
|
|
|
|
|
def setheaders(self):
|
2021-06-24 13:56:22 +08:00
|
|
|
pass
|
|
|
|
# self.headers['Content-Length'] = str(len(self.content))
|
2019-07-10 17:34:45 +08:00
|
|
|
|
|
|
|
class TemplateProcessor(BaseProcessor):
|
|
|
|
@classmethod
|
|
|
|
def isMe(self,name):
|
|
|
|
return name=='tmpl'
|
|
|
|
|
2020-12-20 14:32:08 +08:00
|
|
|
async def path_call(self, request, params={}):
|
2023-07-04 18:16:27 +08:00
|
|
|
await self.set_run_env(request, params=params)
|
2024-02-19 12:41:45 +08:00
|
|
|
path = request.path
|
2019-11-28 15:24:09 +08:00
|
|
|
ns = self.run_ns
|
2019-11-29 18:01:58 +08:00
|
|
|
te = self.run_ns['tmpl_engine']
|
2024-02-18 16:58:00 +08:00
|
|
|
return await te.render(path,**ns)
|
2020-12-20 11:43:00 +08:00
|
|
|
|
|
|
|
async def datahandle(self,request):
|
|
|
|
self.content = await self.path_call(request)
|
2019-07-10 17:34:45 +08:00
|
|
|
|
|
|
|
def setheaders(self):
|
|
|
|
super(TemplateProcessor,self).setheaders()
|
|
|
|
if self.path.endswith('.tmpl.css'):
|
|
|
|
self.headers['Content-Type'] = 'text/css; utf-8'
|
|
|
|
elif self.path.endswith('.tmpl.js'):
|
|
|
|
self.headers['Content-Type'] = 'application/javascript ; utf-8'
|
|
|
|
else:
|
|
|
|
self.headers['Content-Type'] = 'text/html; utf-8'
|
|
|
|
|
2024-01-31 17:08:29 +08:00
|
|
|
class BricksUIProcessor(TemplateProcessor):
|
2020-12-11 12:12:21 +08:00
|
|
|
@classmethod
|
|
|
|
def isMe(self,name):
|
2024-02-18 18:23:40 +08:00
|
|
|
# print(f'{name=} is a bui')
|
2024-01-31 17:08:29 +08:00
|
|
|
return name=='bui'
|
2020-12-11 12:12:21 +08:00
|
|
|
|
|
|
|
async def datahandle(self, request):
|
|
|
|
params = await self.resource.y_env['request2ns']()
|
2024-01-31 17:08:29 +08:00
|
|
|
await super().datahandle(request)
|
|
|
|
if params.get('_webbricks_',None):
|
|
|
|
return
|
2024-01-31 17:43:18 +08:00
|
|
|
txt = self.content
|
|
|
|
entire_url = self.run_ns.get('entire_url')
|
|
|
|
content0 = await self.resource.path_call(request,entire_url('/bricks/header.tmpl'))
|
|
|
|
content2 = await self.resource.path_call(request,entire_url('/bricks/footer.tmpl'))
|
|
|
|
self.content = '%s%s%s' % (content0, txt, content2)
|
2019-07-10 17:34:45 +08:00
|
|
|
|
|
|
|
class PythonScriptProcessor(BaseProcessor):
|
|
|
|
@classmethod
|
|
|
|
def isMe(self,name):
|
|
|
|
return name=='dspy'
|
|
|
|
|
2023-10-12 15:46:05 +08:00
|
|
|
async def loadScript(self, path):
|
2019-07-10 17:34:45 +08:00
|
|
|
data = ''
|
2023-10-12 15:46:05 +08:00
|
|
|
async with aiofiles.open(path,'r', encoding='utf-8') as f:
|
|
|
|
data = await f.read()
|
2019-07-10 17:34:45 +08:00
|
|
|
b= ''.join(data.split('\r'))
|
|
|
|
lines = b.split('\n')
|
|
|
|
lines = ['\t' + l for l in lines ]
|
|
|
|
txt = "async def myfunc(request,**ns):\n" + '\n'.join(lines)
|
|
|
|
return txt
|
|
|
|
|
2020-12-20 14:32:08 +08:00
|
|
|
async def path_call(self, request,params={}):
|
2023-07-04 18:16:27 +08:00
|
|
|
await self.set_run_env(request, params=params)
|
2019-11-28 15:24:09 +08:00
|
|
|
lenv = self.run_ns
|
2019-11-29 11:35:33 +08:00
|
|
|
del lenv['request']
|
2024-02-19 14:02:31 +08:00
|
|
|
txt = await self.loadScript(self.real_path)
|
2023-08-25 10:58:38 +08:00
|
|
|
# print(self.real_path, "#########", txt)
|
2019-12-09 21:07:50 +08:00
|
|
|
exec(txt,lenv,lenv)
|
|
|
|
func = lenv['myfunc']
|
2020-12-16 10:15:43 +08:00
|
|
|
return await func(request,**lenv)
|
|
|
|
|
|
|
|
async def datahandle(self,request):
|
2020-12-20 11:43:00 +08:00
|
|
|
self.content = await self.path_call(request)
|
2019-07-10 17:34:45 +08:00
|
|
|
|
|
|
|
class MarkdownProcessor(BaseProcessor):
|
|
|
|
@classmethod
|
|
|
|
def isMe(self,name):
|
|
|
|
return name=='md'
|
|
|
|
|
|
|
|
async def datahandle(self,request:Request):
|
|
|
|
data = ''
|
2023-10-12 15:46:05 +08:00
|
|
|
async with aiofiles.open(self.real_path,'r',encoding='utf-8') as f:
|
|
|
|
data = await f.read()
|
2021-01-27 17:39:10 +08:00
|
|
|
self.content = self.urlreplace(data, request)
|
2019-07-10 17:34:45 +08:00
|
|
|
|
|
|
|
def urlreplace(self,mdtxt,request):
|
2021-01-27 17:39:10 +08:00
|
|
|
p = '\[(.*)\]\((.*)\)'
|
|
|
|
return re.sub(p,
|
|
|
|
lambda x:'['+x.group(1)+'](' + self.resource.entireUrl(request, x.group(2)) + ')',
|
|
|
|
mdtxt)
|
2019-07-10 17:34:45 +08:00
|
|
|
|
|
|
|
def getProcessor(name):
|
2024-02-18 18:23:40 +08:00
|
|
|
# print(f'getProcessor({name})')
|
2024-02-18 16:13:39 +08:00
|
|
|
return _getProcessor(BaseProcessor, name)
|
2019-07-10 17:34:45 +08:00
|
|
|
|
|
|
|
def _getProcessor(kclass,name):
|
|
|
|
for k in kclass.__subclasses__():
|
|
|
|
if not hasattr(k,'isMe'):
|
|
|
|
continue
|
|
|
|
if k.isMe(name):
|
|
|
|
return k
|
|
|
|
a = _getProcessor(k,name)
|
|
|
|
if a is not None:
|
|
|
|
return a
|
|
|
|
return None
|