ancient.handlers.baseHandler 源代码

from ..model.response import ResponseModel

from tornado import escape
from tornado.web import RequestHandler, HTTPError

import time
from json.decoder import JSONDecodeError


[文档]class BaseHandler(RequestHandler): """ 通过继承 `BaseHandler` 来使用它提供的便利方法,任何一条访问都是一个继承了 `BaseHandler` 的实例化对象 在0.3之后的版本,不建议直接继承BaseHandler,而是通过inheritHandler下的Base间接继承,这样你可以很轻松 的更改路由的父类,如你突然想要给这些子类加入拦截验证功能,你只需要改变inheritHandler/Base的指向就够了。 :param application: tornado.web.Application对象 :param request: HTTPServerRequest对象 (protocol,host,method,uri,version,remote_ip) :param kwargs: 其它在application加入到路由表时添加的额外字段 .. attribute:: request The `tornado.httputil.HTTPServerRequest` object containing additional request parameters including e.g. headers and body data:: request(uri,host,method,header,body,path,query,version,remote_ip,files) .. attribute:: talks_name token或者session id 返回的cookie名称 .. attribute:: json_body 当使用get_json_body方法后用于保存转换成json的body内容 HTTPFile(request.files):: self.request.files.get()方法,获取名称对应的file列表 file文件拥有属性,filename,body,content_type """ def __init__(self, application, request, **kwargs): super(BaseHandler, self).__init__(application, request, **kwargs) self.talks_name = "MtKey" self.json_body = None self.cross_domain = None # @override
[文档] def data_received(self, chunk): """ ``重写方法`` 类加上 `@stream_request_body` 装饰器以后,自动调用的方法 :param chunk: 传入body中的流文件 :return: None """ pass
# @override
[文档] def get_login_url(self): """ ``重写方法`` 自定义login_url地址,返回url地址,当使用@authenticated装饰器时,未验证的连接将跳转的url :return: str """ pass
# @override
[文档] async def prepare(self): """ ``重写方法`` 当实例连接进来需要预先处理内容时调用的函数,例如token认证等任务,写在其中, 不建议直接修改BaseHandler的该方法,应当继承BaseHandler后,重写该方法,并且之后拥有相同 行为的Handler,继续继承同一个被改写prepare的Handler的类 :return: None """ pass
# @override
[文档] def on_finish(self): """ ``重写方法`` 当连接完成所有工作后,收尾时调用的方法,可以写入如sql关闭等任务,与prepare方法一样, 不建议直接改写BaseHandler的该方法,会影响到所有继承BaseHandler的类 :return: None """ pass
# @override
[文档] def on_connection_close(self): """ ``重写方法`` 当连接被意外断开时调用的方法,这个为tornado自带方法,内部有一定处理程序,不建议直接继承重写该方法, 正确的做法是继承BaseHandler对象,重写它的on_close方法 :return: None """ super(BaseHandler, self).on_connection_close() self.on_close()
[文档] def on_close(self): """ 当连接被意外断开时调用的方法,继承BaseHandler的类可以直接重写该方法 :return: None """ pass
# @override
[文档] def write_error(self, status_code, **kwargs): """ ``重写方法`` 当send_error方法被触发时,调用的方法,用来处理错误状态 想要触发原始错误信息,请使用send_error 想要使用json格式错误信息,请使用throw方法 使用send_error会触发tornado系统默认处理,请使用throw触发madtornado来处理错误 :param status_code: 状态码 :param kwargs: 额外参数,如exc_info包含HTTPError的错误信息元组 :return: None """ if self.cross_domain: self.set_access_headers(self.cross_domain) if "exc_info" in kwargs: exception = kwargs["exc_info"][1] log_message = exception.log_message if hasattr(exception, "log_message") else "" self.write_resp(status_code, log_message=log_message, **kwargs) self.finish() else: super(BaseHandler, self).write_error(status_code, **kwargs)
[文档] def write_resp(self, status_code, **kwargs): """ restful风格的自定义错误数据,该错误返回JSON格式错误响应 重写该方法用于自定义错误响应格式,该方法重新时不要抛出错误异常或调用send_error,throw等 :param status_code: 响应码 :param kwargs: 额外参数和log_message :return: None """ resp = ResponseModel() self.set_header('Content-Type', "application/json; charset=UTF-8") resp.status_code = status_code resp.reason = self._reason resp.message = kwargs.get("log_message", "") self.write(resp.get())
[文档] def throw(self, status_code=200, log_message="", **kwargs): """ send_error()方法并不会直接触发系统默认的错误处理样式,如果想使用默认错误处理返回的内容, 请使用throw()方法,注意该方法会被try捕获到,如果写入到try中的时候请注意 常用状态码:: 400 - 请求出现错误,非常通用,不想明确区分的客户端请求出错都可以返回 401 - 没有提供认证信息,未登录或者用户名密码错误 403 - 请求的资源不允许访问,token过期 404 - 请求的内容不存在 405 - 请求的[ 方法 ]不允许使用 406 - 请求格式不正确 408 - 请求超时了 410 - 请求资源曾经存在,但现在不存在了 413 - 请求体过大 414 - 请求的 URI 太长了 415 - 不支持的媒体类型 :param status_code: 状态码 :param log_message: 返回消息 :param kwargs: 额外参数,如{'status_code': 404, 'reason': None} :return: None """ raise HTTPError(status_code, log_message=log_message, **kwargs)
[文档] def write_ok(self): """ 返回一个正常的状态,这个方法和self.throw(200)返回内容是一样的, 但是throw方法会被捕获异常所捕获到,write_ok并不会被捕获 :return: None """ self.write_resp(200)
[文档] def write_dict(self, dict_data, encode_date=False): """ 返回JSON数据响应,该返回为纯粹的数据,错误信息根据状态码进行判定, :param dict_data: dict类型数据 :param encode_date: 是否存在datetime类型的字段 :return: None """ self.write_array(dict_data, encode_date)
[文档] def write_array(self, list_data, encode_date=False): """ 返回JSON数据响应,对象数组 :param list_data: 列表数据 :param encode_date: 是否存在datetime类型的字段 :return: None """ self.set_header('Content-Type', "application/json; charset=UTF-8") self.write(ResponseModel.dumps(list_data, encode_date))
[文档] def write_jsonp(self, key, value): """ 当使用jsonp技术进行请求时,调用此方法,用来直接返回jsonp的内容 :param key: jsonp的名称 :param value: 返回jsonp的内容,多个内容用逗号分隔 :return: None """ self.set_header("Content-Type", "application/x-javascript; charset=UTF-8") jc = self.get_argument(key, None) self.write(str(jc) + '(' + value + ')')
[文档] def get_body2json(self): """ 获取请求的body,将其转换成json数据,并保存在属性json_body中 :return: dict """ if type(self.json_body) is not dict: try: self.json_body = escape.json_decode(self.request.body) except JSONDecodeError as e: self.json_body = {} return self.json_body
[文档] def get_body_argument_for(self, these=None): """ 获取一组body中的form-url格式参数 :param these: 一个字典对象,包含要获取的参数名称和对应的默认值,如果为None获取所有值 :return: dict 获取完成的字典对象,参数名和值相对应 """ return self.__get_arg(these, self.request.body_arguments, self.get_body_argument)
[文档] def get_query_argument_for(self, these=None): """ 获取一组query中的form-url格式参数 :param these: 一个字典对象,包含要获取的参数名称和对应的默认值,如果为None获取所有值 :return: dict 获取完成的字典对象,参数名和值相对应 """ return self.__get_arg(these, self.request.query_arguments, self.get_query_argument)
[文档] def get_argument_for(self, these=None): """ 获取一组query中或者body中的form-url格式参数 :param these: 一个字典对象,包含要获取的参数名称和对应的默认值,如果为None获取所有值 :return: dict 获取完成的字典对象,参数名和值相对应 """ return self.__get_arg(these, self.request.arguments, self.get_argument)
@staticmethod def __get_arg(these, arguments, get_argument): """ 私有方法,用于批量获取参数 :param these: 一个字典对象,包含要获取的参数名称和对应的默认值,如果为None获取所有值 :param arguments: 可以取到所有参数的容器 :param get_argument: 获取参数的方法函数 :return: dict 获取完成的字典对象,参数名和值相对应 """ content = {} if these is None: for arg in arguments: content[arg] = arguments[arg][-1].decode("utf-8") else: for arg in these: content[arg] = get_argument(arg, these[arg]) return content
[文档] def get_body_argument_from(self, these_list): """ 根据传入的参数列表获取参数,如果参数为空值则不返回,从body中查找参数 :param these_list: 想要获取的参数的列表 :return: dict 根据these_list提供的参数列表所能取到的变量键值对 """ return self.__get_arg_from(these_list, self.get_body_argument)
[文档] def get_query_argument_from(self, these_list): """ 根据传入的参数列表获取参数,如果参数为空值则不返回,从query中查找参数 :param these_list: 想要获取的参数的列表 :return: dict 根据these_list提供的参数列表所能取到的变量键值对 """ return self.__get_arg_from(these_list, self.get_query_argument)
[文档] def get_argument_from(self, these_list): """ 根据传入的参数列表获取参数,如果参数为空值则不返回,从body和query中查找参数 :param these_list: 想要获取的参数的列表 :return: dict 根据these_list提供的参数列表所能取到的变量键值对 """ return self.__get_arg_from(these_list, self.get_argument)
@staticmethod def __get_arg_from(these_list, get_argument): """ 私有方法,根据传入的参数列表获取参数,如果参数为空值则不返回 :param these_list: 想要获取的参数的列表 :return: dict 根据these_list提供的参数列表所能取到的变量键值对 """ content = {} for key in these_list: result = get_argument(key, None) if result: content[key] = result return content
[文档] def get_argument_plus(self, arg_name, arg_default=None): """ 获取任意格式传入的参数,可以参数写在链接中,也可以写在body中用json形式保存,也可以x-www-form-urlencoded形式传入body, 调用该方法将自动识别,不支持formdata类型获取,请使用request.files属性自行获取,或者通过data_received回调方法获取 :param arg_name: 参数名称 :param arg_default: 获取不到返回的默认值 :return: 经过处理获取到的值 """ content = self.get_argument(arg_name, None) if content is not None: return content content = self.get_body2json().get(arg_name, None) if content is not None: return content return arg_default
[文档] def get_current_user(self): """ 当使用 `tornado.web.authenticated` 装饰器时调用的方法,如果返回内容,则验证通过,否则自动调整到登录页面,登录地址 设置application中的'login_url': '',参数 :return: str 当前用户的cookie信息 """ return self.get_secure_cookie(self.talks_name)
[文档] def set_current_user(self, value, over_time=3600): """ 设置用户会话cookie :param value: 值,可以是token,也可以是session id :param over_time: 过期时间 :return: None """ self.set_secure_cookie(self.talks_name, value, expires=self.expires_time(over_time))
[文档] def clear_current_user(self): """ 清除用户会话cookie :return: None """ self.clear_cookie(self.talks_name)
[文档] def set_default_headers(self): """ ``重写方法`` 当返回响应的时候,需要设置header信息,调用的默认方法,BaseHandler默认采用text/html方式返回 :return: None """ self.set_header("Content-Type", "text/html; charset=UTF-8")
[文档] def set_stream_headers(self, name): """ 设置返回为流类型,一般用于文件下载 :param name: 文件名称 :return: None """ self.set_header('Content-Type', 'application/octet-stream') self.set_header('Content-Disposition', 'attachment; filename=' + name.encode('utf-8').decode('ISO-8859-1'))
[文档] def set_nocache_headers(self): """ 设置不缓存该文件 :return: None """ self.set_header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
[文档] def set_access_headers(self, domain='*'): """ 设置允许跨域访问 :param domain: 域范围 :return: None """ self.set_header('Access-Control-Allow-Origin', domain) self.set_header('Access-Control-Allow-Headers', '*') self.set_header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS') self.set_header('Access-Control-Max-Age', 600) self.cross_domain = domain
[文档] @staticmethod def expires_time(e_time): """ 对cookie过期时间进行过滤 :param e_time: 过期时间,如3600秒 :return: 赋值给expires的真实值 """ return time.time() + e_time