Skip to content

Commit ec81fa0

Browse files
author
qlopc-msi
committed
调整处理器
1 parent 1321908 commit ec81fa0

File tree

6 files changed

+192
-92
lines changed

6 files changed

+192
-92
lines changed

component/function.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
"""
44
import time
55

6+
import tornado.web
7+
68

79
def mtime():
810
return int(time.time())
11+
12+
13+
def action(path, header, data):
14+
"""请求本地服务,通常用于api接口"""
15+
from quickpython.server.processor import ProcessorHandler
16+
return ProcessorHandler.action(path, header, data)

server/contain/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
from quickpython.component.result import Result
33

44
from .controller import Controller
5-
from .request import Request
5+
from .request import Request, Response
66
from .handler import HandlerHelper

server/contain/controller.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def __initialize__(self, obj, module: str, controller: str, action: str):
3939
self.controller = controller.replace('.', '/')
4040
self.action = action
4141

42-
def __initialize_request__(self, path, params, request):
42+
def __initialize_request__(self, path, params, request: Request):
4343
self.path = path
4444
self.params = params
4545
self.request = request

server/contain/handler.py

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,45 +18,6 @@
1818

1919
class HandlerHelper:
2020

21-
@staticmethod
22-
def before(hdl: "web.RequestHandler"):
23-
request = hdl.request = Request(hdl.request)
24-
request.method = 'POST' if hasattr(hdl, 'method') is None else request.method
25-
# 用户IP
26-
hdl.client_ip = request.remote_ip
27-
# 路径处理
28-
path = hdl.path = hdl.request.path.replace("//", "/")
29-
path_arr = [] if path == '/' else path.split('/')
30-
hdl.path_arr = list(filter(lambda x: len(x) > 0, path_arr))
31-
# 是否ajax
32-
hdl.request.is_ajax = True if request.headers.get('x-requested-with') == 'XMLHttpRequest' else False
33-
34-
@staticmethod
35-
def parse_params(hdl: "web.RequestHandler"):
36-
"""
37-
解析请求数据
38-
支持:get、post、json
39-
"""
40-
request = hdl.request
41-
params = {}
42-
for key in request.query_arguments:
43-
params[key] = hdl.get_query_argument(key)
44-
for key in request.arguments:
45-
params[key] = hdl.get_argument(key)
46-
47-
# json
48-
if request.headers.get('content-type', '').find('application/json') > -1:
49-
try:
50-
body = request.body.decode('utf-8')
51-
content_params = json.loads(body)
52-
params = {**params, **content_params}
53-
except BaseException as e:
54-
logger.error("json请求数据解析异常")
55-
logger.error(e)
56-
57-
hdl.params = request.params = params
58-
return params
59-
6021
@staticmethod
6122
def render_exception(e):
6223
return
@@ -79,7 +40,7 @@ def return_response_code(cls, hdl: "web.RequestHandler", e: ResponseException):
7940
hdl.set_status(e.code)
8041

8142
@classmethod
82-
def return_file(cls, hdl: "web.RequestHandler", path, mime=None):
43+
def return_file(cls, hdl, path, mime=None):
8344
"""
8445
如果是文件且存在就处理
8546
PS: http://127.0.0.1:8107/static/assets/img/logo.png
@@ -96,7 +57,7 @@ def return_file(cls, hdl: "web.RequestHandler", path, mime=None):
9657
return False
9758

9859
@classmethod
99-
def _write_file(cls, hdl: "web.RequestHandler", file_path, max_age=86400, mime=None):
60+
def _write_file(cls, hdl, file_path, max_age=86400, mime=None):
10061
# 直接输出二进制内容
10162
if isinstance(file_path, bytes):
10263
hdl.set_header('content-type', "application/octet-stream" if mime is None else mime)

server/contain/request.py

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,93 @@
11

2+
import logging, json
23
from ..common import *
34

5+
logger = logging.getLogger(__name__)
46

5-
class Request: # type: httputil.HTTPServerRequest
67

7-
def __init__(self, target):
8-
super().__init__()
9-
self.__target = target # type: httputil.HTTPServerRequest
8+
class Request:
109

11-
def __getattr__(self, name):
12-
return getattr(self.__target, name)
10+
def __init__(self):
11+
self.status = 200
12+
self.headers = {}
13+
self.method = None
14+
self.path = None
15+
self.remote_ip = None
16+
self.query_arguments = None
17+
self.arguments = None
18+
self.__target = None
19+
20+
def __load_from_tornado__(self, req, hdl):
21+
"""从tornado加载请求信息"""
22+
self.__target = req
23+
self.status = hdl.get_status()
24+
self.remote_ip = req.remote_ip
25+
# 路径处理
26+
path = self.path = req.path.replace("//", "/")
27+
path_arr = [] if path == '/' else path.split('/')
28+
self.path_arr = list(filter(lambda x: len(x) > 0, path_arr))
29+
# 复制headers
30+
self.headers = dict(req.headers)
31+
self.query_arguments = dict(req.query_arguments)
32+
self.arguments = dict(req.arguments)
33+
self.body = req.body
34+
# 解析数据
35+
params = {}
36+
for key in req.query_arguments:
37+
params[key] = req.get_query_argument(key)
38+
for key in req.arguments:
39+
params[key] = req.get_argument(key)
40+
41+
# json
42+
if self.headers.get('content-type', '').find('application/json') > -1:
43+
try:
44+
body = self.body.decode('utf-8')
45+
content_params = json.loads(body)
46+
params = {**params, **content_params}
47+
except BaseException as e:
48+
logger.error("json请求数据解析异常")
49+
logger.error(e)
50+
51+
self.params = params
1352

1453
def is_post(self):
15-
return self.__target.method == 'POST'
54+
return self.method == 'POST'
1655

1756
def is_get(self):
18-
return self.__target.method == 'GET'
57+
return self.method == 'GET'
58+
59+
def is_ajax(self):
60+
return True if self.headers.get('x-requested-with') == 'XMLHttpRequest' else False
61+
62+
def ip(self):
63+
return self.remote_ip
64+
65+
66+
class Response:
67+
"""返回头"""
68+
69+
def __init__(self):
70+
self.status = 200
71+
self.status_msg = None
72+
self.headers = {}
73+
self.body = None # 返回内容
74+
75+
def set_header(self, key, val):
76+
self.headers[key] = val
77+
78+
def write(self, body):
79+
if self.body is None:
80+
self.body = bytes()
81+
if isinstance(body, bytes) is False:
82+
body = str(body, encoding="utf8")
83+
self.body += body
84+
85+
def finish(self, hdl):
86+
# 写入header
87+
if len(self.headers) > 0:
88+
for k, v in self.headers.items():
89+
hdl.set_header(k, v)
90+
91+
# 将body写入tornado
92+
if self.body is not None:
93+
hdl.write(self.body)

server/processor.py

Lines changed: 97 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,76 +10,74 @@
1010
from quickpython.component.function import *
1111
from quickpython.component.result import Result
1212
from .exception import *
13-
from .contain import Controller, Request, HandlerHelper
13+
from .contain import Controller, Request, Response, HandlerHelper
1414

1515
logger = logging.getLogger(__name__)
1616
logger.setLevel(logging.INFO)
1717
encoding = Config.SETTINGS['encoding']
1818
DS = r"/"
1919

2020

21-
class ProcessorHandler(web.RequestHandler):
21+
class Application:
22+
pass
2223

23-
executor = ThreadPoolExecutor(max_workers=Config.web_thr_count(Config.SETTINGS['pro_thr_num']))
2424

25-
def __init__(self, application: "Application", request: httputil.HTTPServerRequest, **kwargs: Any):
26-
super().__init__(application, Request(request), **kwargs)
25+
class QuickPythonHandler:
26+
27+
def __init__(self, application: Application, request: Request, hdl=None):
28+
self.application = application
29+
self.request = request
30+
self.response = Response()
31+
self._hdl = hdl # tornado的hdl
2732
self.params = {} # 收集到的请求参数
28-
self.path = '/' # 请求路径
29-
self.path_arr = [] # 请求路径分割数组
33+
self._is_finish = False
3034

31-
def data_received(self, chunk: bytes) -> Optional[Awaitable[None]]:
32-
pass
35+
@classmethod
36+
def action(cls, path, header=None, data=None):
37+
"""本地接口直接调用"""
3338

34-
@tornado.gen.coroutine
35-
def get(self, *args, **kwargs):
36-
self.request.method = 'GET'
37-
resp_content = yield self._dispose(*args)
38-
if resp_content is True:
39-
self.finish()
40-
return
41-
if self.response_write(resp_content) is False: # =False是未处理
42-
self.finish()
43-
return
39+
def __dispose__(self):
40+
try:
41+
ret = self.__dispose()
42+
except BaseException as e:
43+
ret = e
4444

45-
@tornado.gen.coroutine
46-
def post(self, *args, **kwargs):
47-
self.request.method = 'POST'
48-
resp_content = yield self._dispose(*args)
49-
if resp_content is True:
50-
self.finish()
51-
return
52-
if self.response_write(resp_content) is False: # =False是未处理
53-
self.finish()
54-
return
45+
if ret is not None:
46+
self.response_write(ret)
5547

56-
@run_on_executor
57-
def _dispose(self, *args):
48+
self.finish()
49+
50+
def __dispose(self):
51+
ret = None
5852
try:
59-
# 初始数据
53+
# 初始
54+
request = self.request
6055
self._on_mtime = int(time.time() * 1000)
6156
self._is_finish = False # 请求是否结束
6257
self._is_res_request = False # 是否是资源请求
6358
# 请求处理
64-
HandlerHelper.before(self)
65-
logger.debug("method={}, args={}".format(self.request.method, args))
59+
logger.debug("method={}, path={}".format(request.method, request.path))
60+
6661
# 是否是资源文件下载(需要对upload进行鉴权处理
67-
if HandlerHelper.return_file(self, self.path):
62+
if HandlerHelper.return_file(self, request.path):
6863
self._is_res_request = True
6964
return True
65+
7066
# 收集请求参数
71-
params = self.params = HandlerHelper.parse_params(self)
72-
logger.debug("path={}, params={}".format(self.path, params))
67+
params = self.params = self.request.params
68+
logger.debug("path={}, params={}".format(request.path, params))
69+
7370
# 寻找控制器
74-
controller, controller_action = self.find_controller_action(self, self.path, self.path_arr)
75-
controller.__initialize_request__(self.path, params, self.request)
71+
controller, controller_action = self.find_controller_action(self, self.request)
72+
controller.__initialize_request__(request.path, params, self.request)
7673

7774
# 执行控制器方法
7875
# hooker.trigger('request_before', controller)
7976
ret = controller_action()
8077
# hooker.trigger('request_after', controller)
8178

82-
return "None" if ret is None else ret
79+
ret = "None" if ret is None else ret
80+
return ret
8381

8482
except ResponseException as e:
8583
return e
@@ -174,8 +172,9 @@ def scan_file_class(cls, file):
174172
return ret
175173

176174
@classmethod
177-
def find_controller_action(cls, pro_obj, path, path_arr):
175+
def find_controller_action(cls, pro_obj, request):
178176
"""找到对应控制器和方法"""
177+
path, path_arr = request.path, request.path_arr
179178
pa = path_arr[1:] if len(path_arr) > 0 and path_arr[0] == '' else path_arr
180179
if len(pa) == 0 or pa[0] == '':
181180
pa.extend(["index", "index", "index"])
@@ -224,6 +223,7 @@ def _response_write(self, ret, status_code=200):
224223
logger.exception(e)
225224
ret = ResponseException("页面异常:{}".format(str(e)), code=500)
226225
return HandlerHelper.return_response(self, ret)
226+
227227
elif isinstance(ret, ResponseFileException):
228228
return HandlerHelper.return_file(self, ret.file, ret.mime)
229229
elif isinstance(ret, ResponseException):
@@ -249,5 +249,61 @@ def _response_write(self, ret, status_code=200):
249249

250250
return False
251251

252+
def get_status(self):
253+
return self.request.status
254+
255+
def set_status(self, status):
256+
self.response.status = status
257+
258+
def set_header(self, key, val):
259+
self.response.set_header(key, val)
260+
261+
def write(self, content=None):
262+
self.response.write(content)
263+
264+
def render(self, template_name, **kwargs):
265+
"""渲染模板"""
266+
if self._hdl is not None:
267+
html = self._hdl.render_string(template_name, **kwargs)
268+
self.response.write(html)
269+
270+
def finish(self):
271+
"""结束"""
272+
if self._hdl is not None:
273+
self.response.finish(self._hdl)
274+
252275
def on_finish(self):
253276
self._is_finish = True
277+
278+
279+
class ProcessorHandler(web.RequestHandler):
280+
"""嫁接tornado框架"""
281+
282+
executor = ThreadPoolExecutor(max_workers=Config.web_thr_count(Config.SETTINGS['pro_thr_num']))
283+
284+
def initialize(self):
285+
request = Request()
286+
request.__load_from_tornado__(self.request, self)
287+
self._hdl = QuickPythonHandler(Application(), request, self)
288+
289+
def data_received(self, chunk: bytes) -> Optional[Awaitable[None]]:
290+
pass
291+
292+
@tornado.gen.coroutine
293+
def get(self, *args, **kwargs):
294+
self._hdl.request.method = 'GET'
295+
yield self._dispose(*args)
296+
297+
@tornado.gen.coroutine
298+
def post(self, *args, **kwargs):
299+
self._hdl.request.method = 'POST'
300+
yield self._dispose(*args)
301+
302+
@run_on_executor
303+
def _dispose(self, *args):
304+
pass
305+
logger.info("处理请求")
306+
return self._hdl.__dispose__()
307+
308+
def on_finish(self):
309+
self._hdl.on_finish()

0 commit comments

Comments
 (0)