add restful support
This commit is contained in:
parent
3290fe1f97
commit
260c38d637
14
ahserver/error.py
Normal file
14
ahserver/error.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
def Error(errno='undefined error',msg='Error'):
|
||||||
|
return {
|
||||||
|
"status":"Error",
|
||||||
|
"data":{
|
||||||
|
"message":msg,
|
||||||
|
"errno":errno
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def Success(data):
|
||||||
|
return {
|
||||||
|
"status":"OK",
|
||||||
|
"data":data
|
||||||
|
}
|
@ -20,10 +20,6 @@ from appPublic.uniqueID import setNode,getID
|
|||||||
from appPublic.unicoding import unicoding,uDict,uObject
|
from appPublic.unicoding import unicoding,uDict,uObject
|
||||||
from appPublic.Singleton import SingletonDecorator
|
from appPublic.Singleton import SingletonDecorator
|
||||||
|
|
||||||
from sql.crud import _CRUD,CRUD
|
|
||||||
# from sql.sqlorAPI import DBPools,runSQL,runSQLPaging,runSQLIterator
|
|
||||||
# from sql.sqlorAPI import getTables,getTableFields,getTablePrimaryKey
|
|
||||||
# from sql.sqlorAPI import getTableForignKeys,runSQLResultFields
|
|
||||||
from sqlor.dbpools import DBPools
|
from sqlor.dbpools import DBPools
|
||||||
|
|
||||||
|
|
||||||
@ -167,7 +163,6 @@ def initEnv():
|
|||||||
g.folderInfo = folderInfo
|
g.folderInfo = folderInfo
|
||||||
g.abspath = abspath
|
g.abspath = abspath
|
||||||
g.request2ns = request2ns
|
g.request2ns = request2ns
|
||||||
g.CRUD = CRUD
|
|
||||||
g.data2xlsx = data2xlsx
|
g.data2xlsx = data2xlsx
|
||||||
g.xlsxdata = XLSXData
|
g.xlsxdata = XLSXData
|
||||||
g.openfile = openfile
|
g.openfile = openfile
|
||||||
|
@ -19,7 +19,7 @@ from aiohttp.web_routedef import AbstractRouteDef
|
|||||||
|
|
||||||
from appPublic.jsonConfig import getConfig
|
from appPublic.jsonConfig import getConfig
|
||||||
from appPublic.MiniI18N import getI18N
|
from appPublic.MiniI18N import getI18N
|
||||||
from appPublic.dictObject import DictObject
|
from appPublic.dictObject import DictObject, multiDict2Dict
|
||||||
|
|
||||||
from .baseProcessor import getProcessor
|
from .baseProcessor import getProcessor
|
||||||
from .xlsxdsProcessor import XLSXDataSourceProcessor
|
from .xlsxdsProcessor import XLSXDataSourceProcessor
|
||||||
@ -27,19 +27,7 @@ from .sqldsProcessor import SQLDataSourceProcessor
|
|||||||
from .serverenv import ServerEnv
|
from .serverenv import ServerEnv
|
||||||
from .url2file import Url2File
|
from .url2file import Url2File
|
||||||
from .filestorage import FileStorage
|
from .filestorage import FileStorage
|
||||||
|
from .restful import DBCrud
|
||||||
def multiDict2Dict(md):
|
|
||||||
ns = {}
|
|
||||||
for k,v in md.items():
|
|
||||||
ov = ns.get(k,None)
|
|
||||||
if ov is None:
|
|
||||||
ns[k] = v
|
|
||||||
elif type(ov) == type([]):
|
|
||||||
ov.append(v)
|
|
||||||
ns[k] = ov
|
|
||||||
else:
|
|
||||||
ns[k] = [ov,v]
|
|
||||||
return ns
|
|
||||||
|
|
||||||
def getHeaderLang(request):
|
def getHeaderLang(request):
|
||||||
al = request.headers.get('Accept-Language')
|
al = request.headers.get('Accept-Language')
|
||||||
@ -70,6 +58,10 @@ class ProcessorResource(StaticResource):
|
|||||||
append_version=append_version)
|
append_version=append_version)
|
||||||
gr = self._routes.get('GET')
|
gr = self._routes.get('GET')
|
||||||
self._routes.update({'POST':gr})
|
self._routes.update({'POST':gr})
|
||||||
|
self._routes.update({'PUT':gr})
|
||||||
|
self._routes.update({'OPTIONS':gr})
|
||||||
|
self._routes.update({'DELETE':gr})
|
||||||
|
self._routes.update({'TRACE':gr})
|
||||||
self.y_processors = []
|
self.y_processors = []
|
||||||
self.y_prefix = prefix
|
self.y_prefix = prefix
|
||||||
self.y_directory = directory
|
self.y_directory = directory
|
||||||
@ -90,7 +82,7 @@ class ProcessorResource(StaticResource):
|
|||||||
real_path = os.path.abspath(rp)
|
real_path = os.path.abspath(rp)
|
||||||
return real_path
|
return real_path
|
||||||
|
|
||||||
async def getPostData(self,request):
|
async def getPostData(self,request: Request) -> dict:
|
||||||
reader = await request.multipart()
|
reader = await request.multipart()
|
||||||
if reader is None:
|
if reader is None:
|
||||||
md = await request.post()
|
md = await request.post()
|
||||||
@ -161,8 +153,6 @@ class ProcessorResource(StaticResource):
|
|||||||
return await self.getPostData(request)
|
return await self.getPostData(request)
|
||||||
ns = multiDict2Dict(request.query)
|
ns = multiDict2Dict(request.query)
|
||||||
return ns
|
return ns
|
||||||
print('** ret=',ret,request.query)
|
|
||||||
return ns
|
|
||||||
|
|
||||||
self.y_env.i18n = serveri18n
|
self.y_env.i18n = serveri18n
|
||||||
self.y_env.i18nDict = i18nDICT
|
self.y_env.i18nDict = i18nDICT
|
||||||
@ -172,6 +162,19 @@ class ProcessorResource(StaticResource):
|
|||||||
self.y_env.request2ns = getArgs
|
self.y_env.request2ns = getArgs
|
||||||
self.y_env.resource = self
|
self.y_env.resource = self
|
||||||
path = request.path
|
path = request.path
|
||||||
|
config = getConfig()
|
||||||
|
if config.website.dbrest and path.startswith(config.website.dbrest):
|
||||||
|
pp = path.split('/')[2:]
|
||||||
|
if len(pp)<2:
|
||||||
|
raise HTTPNotFound
|
||||||
|
dbname = pp[0]
|
||||||
|
tablename = pp[1]
|
||||||
|
id = None
|
||||||
|
if len(pp) > 2:
|
||||||
|
id = pp[2]
|
||||||
|
crud = DBCrud(request,dbname,tablename,id=id)
|
||||||
|
return await crud.dispatch()
|
||||||
|
|
||||||
for word, handlername in self.y_processors:
|
for word, handlername in self.y_processors:
|
||||||
if path.endswith(word):
|
if path.endswith(word):
|
||||||
Klass = getProcessor(handlername)
|
Klass = getProcessor(handlername)
|
||||||
|
123
ahserver/restful.py
Normal file
123
ahserver/restful.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
from aiohttp.web_urldispatcher import StaticResource, _WebHandler, PathLike
|
||||||
|
from aiohttp.web_urldispatcher import Optional, _ExpectHandler
|
||||||
|
from aiohttp.web_urldispatcher import Path
|
||||||
|
from aiohttp.web_response import Response, StreamResponse
|
||||||
|
from aiohttp.web_exceptions import (
|
||||||
|
HTTPException,
|
||||||
|
HTTPExpectationFailed,
|
||||||
|
HTTPForbidden,
|
||||||
|
HTTPMethodNotAllowed,
|
||||||
|
HTTPNotFound,
|
||||||
|
)
|
||||||
|
from aiohttp import web
|
||||||
|
from aiohttp.web_fileresponse import FileResponse
|
||||||
|
from aiohttp.web_request import Request
|
||||||
|
from aiohttp.web_response import Response, StreamResponse
|
||||||
|
from aiohttp.web_routedef import AbstractRouteDef
|
||||||
|
from aiohttp.web import json_response
|
||||||
|
|
||||||
|
|
||||||
|
from sqlor.crud import CRUD
|
||||||
|
|
||||||
|
from appPublic.dictObject import multiDict2Dict
|
||||||
|
from appPublic.jsonConfig import getConfig
|
||||||
|
|
||||||
|
from .error import Error,Success
|
||||||
|
|
||||||
|
DEFAULT_METHODS = ('GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE')
|
||||||
|
|
||||||
|
class RestEndpoint:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.methods = {}
|
||||||
|
|
||||||
|
for method_name in DEFAULT_METHODS:
|
||||||
|
method = getattr(self, method_name.lower(), None)
|
||||||
|
if method:
|
||||||
|
self.register_method(method_name, method)
|
||||||
|
|
||||||
|
def register_method(self, method_name, method):
|
||||||
|
self.methods[method_name.upper()] = method
|
||||||
|
|
||||||
|
async def dispatch(self):
|
||||||
|
method = self.methods.get(self.request.method.upper())
|
||||||
|
if not method:
|
||||||
|
raise HTTPMethodNotAllowed('', DEFAULT_METHODS)
|
||||||
|
|
||||||
|
return await method()
|
||||||
|
|
||||||
|
|
||||||
|
class DBCrud(RestEndpoint):
|
||||||
|
def __init__(self, request,dbname,tablename, id=None):
|
||||||
|
print(f'***{dbname}*{tablename}*{id}************')
|
||||||
|
super().__init__()
|
||||||
|
self.dbname = dbname
|
||||||
|
self.tablename = tablename
|
||||||
|
self.request = request
|
||||||
|
self.id = id
|
||||||
|
try:
|
||||||
|
self.crud = CRUD(dbname,tablename)
|
||||||
|
except Exception as e:
|
||||||
|
print('e=',e)
|
||||||
|
raise HTTPNotFound
|
||||||
|
|
||||||
|
async def options(self) -> Response:
|
||||||
|
try:
|
||||||
|
d = await self.crud.I()
|
||||||
|
return json_response(Success(d))
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return json_response(Error(errno='metaerror',msg='get metadata error'))
|
||||||
|
|
||||||
|
async def get(self) -> Response:
|
||||||
|
"""
|
||||||
|
query data
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
ns = multiDict2Dict(self.request.query)
|
||||||
|
if self.id is not None:
|
||||||
|
ns['__id'] = self.id
|
||||||
|
d = await self.crud.R(NS=ns)
|
||||||
|
return json_response(Success(d))
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return json_response(Error(errno='search error',msg='search error'))
|
||||||
|
|
||||||
|
async def post(self):
|
||||||
|
"""
|
||||||
|
insert data
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
ns = multiDict2Dict(await self.request.post())
|
||||||
|
d = await self.crud.C(ns)
|
||||||
|
return json_response(Success(d))
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return json_response(Error(errno='add error',msg='add error'))
|
||||||
|
|
||||||
|
async def put(self):
|
||||||
|
"""
|
||||||
|
update data
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
ns = multiDict2Dict(await self.request.post())
|
||||||
|
d = await self.crud.U(ns)
|
||||||
|
return json_response(Success(''))
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return json_response(Error(errno='update error',msg='update error'))
|
||||||
|
|
||||||
|
async def delete(self, request: Request, instance_id):
|
||||||
|
"""
|
||||||
|
delete data
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
ns = multiDict2Dict(self.request.query)
|
||||||
|
d = await self.crud.D(ns)
|
||||||
|
return json_response(Success(d))
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return json_response(Error(erron='delete error',msg='error'))
|
@ -43,6 +43,7 @@
|
|||||||
"index.dspy",
|
"index.dspy",
|
||||||
"index.md"
|
"index.md"
|
||||||
],
|
],
|
||||||
|
"dbrest":"/dbs",
|
||||||
"visualcoding":{
|
"visualcoding":{
|
||||||
"default_root":"/samples/vc/test",
|
"default_root":"/samples/vc/test",
|
||||||
"userroot":{
|
"userroot":{
|
||||||
|
@ -11,4 +11,5 @@ sqlor
|
|||||||
jinja2
|
jinja2
|
||||||
ujson
|
ujson
|
||||||
openpyxl
|
openpyxl
|
||||||
#appPublic
|
appPublic
|
||||||
|
patterncoding
|
||||||
|
Loading…
Reference in New Issue
Block a user