# -*- coding: utf-8
#------------------------------------------------------------------#
__author__ = "Xavier MARCELET <xavier@marcelet.com>"
__version__ = "0.3"
#------------------------------------------------------------------#
import json
import cherrypy
from xtd.core import logger, error, stat
#------------------------------------------------------------------#
[docs]def log_request_response(p_withResponse):
def enc(p_val):
if isinstance(p_val, bytes):
return p_val.decode("utf-8")
return p_val
def print_part(p_part):
return {
"name" : enc(p_part.name),
"headers" : { enc(x):enc(y) for x,y in p_part.headers.items() },
"value" : enc(p_part.fullvalue())
}
l_request = cherrypy.serving.request
l_remote = l_request.remote
l_data = {
"request" : {
"name" : enc(l_remote.name),
"ip" : enc(l_remote.ip),
"line" : enc(l_request.request_line),
"headers" : { enc(x):enc(y) for x,y in l_request.headers.items() },
"body" : {}
}
}
# Request parameters from URL query string and
# x-www-form-urlencoded POST data
if l_request.body.params:
l_body = l_data["request"]["body"]
l_body["params"] = {}
for c_name, c_value in l_request.body.params.items():
if not c_name in l_body["params"]:
l_body["params"][enc(c_name)] = {}
if isinstance(c_value, list):
for c_pos, c_item in enumerate(c_value):
if not c_pos in l_body["params"][enc(c_name)]:
l_body["params"][enc(c_name)][c_pos] = {}
# pylint: disable=protected-access
if isinstance(c_item, cherrypy._cpreqbody.Part):
l_body["params"][enc(c_name)][c_pos] = print_part(c_item)
else:
l_body["params"][enc(c_name)][c_pos] = {
"value" : enc(c_item)
}
else:
l_body["params"][enc(c_name)] = enc(c_value)
if not p_withResponse:
return l_data
# If the body is multipart format each of the parts
if l_request.body.parts:
l_body = l_data["request"]["body"]
l_body["parts"] = {}
for c_pos, c_part in enumerate(l_request.body.parts):
l_body["parts"][c_pos] = print_part(c_part)
l_headers = {}
if cherrypy.response.header_list:
l_headers = { enc(x):enc(y) for x,y in cherrypy.response.header_list }
l_data["response"] = {
"status" : enc(cherrypy.response.status),
"headers" : l_headers,
"body" : {
"chunks" : []
}
}
if not cherrypy.response.stream:
try:
for c_chunk in cherrypy.response.body:
l_data["response"]["body"]["chunks"].append(enc(c_chunk))
except BaseException:
l_data["response"]["body"]["chunks"] = []
return l_data
[docs]def request_logger():
#pylint: disable=invalid-name
def handle(level, module):
l_data = log_request_response(False)
l_val = json.dumps(l_data, indent=2)
for c_line in l_val.split("\n"):
logger.log(level, module, c_line)
return handle
[docs]def response_logger():
#pylint: disable=invalid-name
def handle(level, module):
l_data = log_request_response(True)
l_val = json.dumps(l_data, indent=2)
for c_line in l_val.split("\n"):
logger.log(level, module, c_line)
return handle
[docs]def perf_begin():
#pylint: disable=invalid-name
def handle(ns, name):
try:
l_counter = stat.manager.StatManager().get(ns, name)
except error.XtdError:
l_counter = stat.counter.Perf(name)
stat.manager.StatManager().register_counter(ns, l_counter)
l_counter.work_begin()
return handle
[docs]def perf_end():
#pylint: disable=invalid-name
def handle(ns, name):
try:
l_counter = stat.manager.StatManager().get(ns, name)
except error.XtdError:
l_counter = stat.counter.Perf(name)
stat.manager.StatManager().register_counter(ns, l_counter)
l_counter.work_end()
return handle
[docs]class JsonHTTPError(cherrypy.HTTPError):
[docs] def __init__(self, p_status, p_message):
super(JsonHTTPError, self).__init__(p_status, p_message)
self.m_message = p_message
[docs] def set_response(self):
cherrypy.response.status = self.code
cherrypy.response.headers["Content-Type"] = "application/json"
cherrypy.response.body = json.dumps({
"status" : "%d - %s" % (self.code, self.reason),
"message" : self.m_message
}).encode("utf-8")