11import json
2+ import pathlib
23import typing
4+ from datetime import datetime
35
6+ from jinja2 import Environment
7+ from jinja2 import FileSystemLoader
8+ from superannotate .logger import get_server_logger
49from werkzeug .exceptions import HTTPException
510from werkzeug .routing import Map
611from werkzeug .routing import Rule
712from werkzeug .serving import run_simple
813from werkzeug .wrappers import Request
9- from werkzeug .wrappers import Response
14+ from werkzeug .wrappers import Response as BaseResponse
15+
16+ logger = get_server_logger ()
17+
18+
19+ class Response (BaseResponse ):
20+ ...
1021
1122
1223class SingletonMeta (type ):
@@ -23,8 +34,14 @@ class SAServer(metaclass=SingletonMeta):
2334 def __init__ (self ):
2435 self ._url_map : Map = Map ([])
2536 self ._view_function_map : typing .Dict [str , typing .Callable ] = {}
37+ self .jinja_env = Environment (
38+ loader = FileSystemLoader (str (pathlib .Path (__file__ ).parent / "templates" )),
39+ autoescape = True ,
40+ )
2641
27- def route (self , rule : str , methods : typing .List [str ] = None , ** options : typing .Any ):
42+ def route (
43+ self , rule : str , methods : typing .List [str ] = None , ** options : typing .Any
44+ ) -> typing .Any :
2845 """Decorate a view function to register it with the given URL
2946 rule and options. Calls :meth:`add_url_rule`, which has more
3047 details about the implementation.
@@ -135,17 +152,47 @@ def index():
135152 def _dispatch_request (self , request ):
136153 """Dispatches the request."""
137154 adapter = self ._url_map .bind_to_environ (request .environ )
155+ response = None
156+ content = None
138157 try :
139158 endpoint , values = adapter .match ()
140159 view_func = self ._view_function_map .get (endpoint )
141160 if not view_func :
142161 return Response (status = 404 )
143- response = view_func (request , ** values )
144- if isinstance (response , dict ):
145- return Response (json .dumps (response ), content_type = "application/json" )
146- return Response (response )
162+ content = view_func (request , ** values )
163+ if isinstance (content , Response ):
164+ response = content
165+ elif isinstance (content , (list , dict )):
166+ response = Response (
167+ json .dumps (content ), content_type = "application/json"
168+ )
169+ else :
170+ response = Response (content )
171+ return response
147172 except HTTPException as e :
148173 return e
174+ finally :
175+ if "monitor" not in request .full_path and "log" not in request .full_path :
176+ data = {
177+ "date" : datetime .now ().strftime ("%Y-%m-%d %H:%M:%S" ),
178+ "request" : {
179+ "method" : request .full_path ,
180+ "path" : request .url ,
181+ "headers" : dict (request .headers .items ()),
182+ "data" : request .data .decode ("utf-8" ),
183+ },
184+ "response" : {
185+ "headers" : dict (request .headers .items ()) if response else None ,
186+ # 'data': response.data.decode('utf-8') if response else None,
187+ "data" : content .data .decode ("utf-8" )
188+ if isinstance (content , Response )
189+ else content ,
190+ "status_code" : response .status_code if response else None ,
191+ },
192+ }
193+ # import ndjson
194+ print (11111 , request .full_path )
195+ logger .info (json .dumps (data ))
149196
150197 def wsgi_app (self , environ , start_response ):
151198 """WSGI application that processes requests and returns responses."""
@@ -197,3 +244,7 @@ def run(
197244 ssl_context = ssl_context ,
198245 ** kwargs
199246 )
247+
248+ def render_template (self , template_name , ** context ):
249+ t = self .jinja_env .get_template (template_name )
250+ return Response (t .render (context ), mimetype = "text/html" )
0 commit comments