app.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. # note: https://responder.kennethreitz.org/en/latest/search.html?q=resp.content
  2. from hub import methods
  3. def generate_app():
  4. """"""
  5. from api.url import action_methods
  6. # from factories.line_manage import LineManage
  7. # see: https://lzomedia.com/blog/host-fastapi-backend-api-and-react-app-frontend-locally/
  8. # --- define middleware --- see: https://www.starlette.io/middleware/
  9. # from starlette.applications import Starlette
  10. # from starlette.middleware import Middleware
  11. # # from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
  12. # # from starlette.middleware.trustedhost import TrustedHostMiddlewar
  13. # middleware = [
  14. # Middleware(
  15. # TrustedHostMiddleware,
  16. # allow_credentials=True,
  17. # allowed_hosts=['*'],
  18. # allow_methods=["*"],
  19. # allow_headers=["*"],
  20. # ),
  21. # # Middleware(HTTPSRedirectMiddleware)
  22. # ]
  23. # --- define app --- see: https://responder.kennethreitz.org/en/latest/tour.html#cors
  24. import responder
  25. app = responder.API(
  26. # cors=True,
  27. # allow_methods=['*'],
  28. # allow_credentials=True,
  29. )
  30. async def coroutine_method(module, method, _params):
  31. """协程方法"""
  32. # run_at = time.time()
  33. result = await getattr(module, method)(**_params)
  34. # methods.debug_log(f"app.coroutine_method", f"use time {round(time.time() - run_at, 2)}s")
  35. return result
  36. def foreground_method(module, method, _params):
  37. """等待返回"""
  38. # run_at = time.time()
  39. result = getattr(module, method)(**_params)
  40. # methods.debug_log(f"app.foreground_method", f"use time {round(time.time() - run_at, 2)}s")
  41. return result
  42. @app.background.task
  43. def background_method(module, method, _params):
  44. """不等返回"""
  45. # run_at = time.time()
  46. result = getattr(module, method)(**_params)
  47. # methods.debug_log(f"app.background_method", f"use time {round(time.time() - run_at, 2)}s")
  48. return result
  49. async def run_method(_method_key, _params):
  50. if _method_key not in action_methods:
  51. return dict(code=3, details=f"{_method_key} not found!")
  52. else:
  53. module, method, method_type = action_methods[_method_key]
  54. del _params['module']
  55. del _params['method']
  56. if method_type == 'IsAsync':
  57. return await coroutine_method(module, method, _params)
  58. elif method_type == 'IsBack':
  59. return foreground_method(module, method, _params)
  60. elif method_type == 'NoBack':
  61. return background_method(module, method, _params)
  62. @app.route('/api')
  63. async def web_api(request, response):
  64. try:
  65. if request.params:
  66. params = dict(request.params.items())
  67. else:
  68. params = await request.media()
  69. # --- todo 存在get请求只能接受一个参数的问题 ---
  70. if 'mp3_name' in params:
  71. params['module'] = 'TEST'
  72. params['method'] = 'test011'
  73. methods.debug_log('app.web_api', f"m-60: params is {params}")
  74. if not params.get('module'):
  75. response.media = dict(code=1, details=f"module is null!")
  76. elif not params.get('method'):
  77. response.media = dict(code=2, details=f"method is null!")
  78. else:
  79. method_key = f"{params.get('module')}.{params.get('method')}"
  80. result = await run_method(method_key, params)
  81. if result.__class__.__name__ == 'bytes':
  82. response.content = result
  83. elif result.__class__.__name__ == 'str':
  84. response.text = result
  85. elif result.__class__.__name__ == 'dict':
  86. response.media = result
  87. elif result.__class__.__name__ == 'Future':
  88. response.media = dict(code=0, details=f"{result} is running.")
  89. elif not result:
  90. response.media = dict(code=0, details=f"return is null.")
  91. else:
  92. response.media = dict(code=0, details=f"return type is {result.__class__.__name__}.")
  93. except Exception as exception:
  94. methods.debug_log('app.web_api', f"m-86: exception | {exception}")
  95. methods.debug_log('app.web_api', f"m-86: traceback | {methods.trace_log()}")
  96. response.media = dict(code=-1, details=f"{methods.trace_log()}")
  97. @app.route('/line', websocket=True)
  98. async def line(ws):
  99. """
  100. let wsuri = `${location.protocol === 'https' ? 'wss' : 'ws'}://${location.host}:8801/line`;
  101. connect_json_text = {
  102. line_id: 连接id,暂为token
  103. }
  104. )
  105. send_json_text_1 = {
  106. face_uuid: 匹配到的人脸id
  107. face_name: 人脸名称
  108. input_face_b64: 抓拍图片(b64格式字符串)
  109. }
  110. """
  111. try:
  112. await ws.accept()
  113. while True:
  114. data = await ws.receive_text() # 消息接受方法 receive_{text/json/bytes}
  115. if not data:
  116. methods.debug_log('app.line', f"error code is 1!")
  117. break
  118. if not methods.is_json(data):
  119. methods.debug_log('app.line', f"error code is 2!")
  120. break
  121. data = methods.json_loads(data)
  122. # methods.debug_log('app.line', f"data: {data}")
  123. if not data.get('line_id'):
  124. methods.debug_log('api.line', f"error code is 3!")
  125. break
  126. # --- check ---
  127. if not data.get('line_id'):
  128. methods.debug_log('api.line', f"error code is 4!")
  129. break
  130. # --- save ---
  131. line_id = data.get('line_id')
  132. # LineManage.line_dict[line_id] = ws
  133. except Exception as exception:
  134. if exception.__class__.__name__ == 'WebSocketDisconnect':
  135. await ws.close()
  136. else:
  137. methods.debug_log('app.line', f"m-136: exception | {exception}")
  138. methods.debug_log('app.line', f"m-136: traceback | {methods.trace_log()}")
  139. # --- return ---
  140. return app