Tornado

来自百合仙子's Wiki
跳转到导航 跳转到搜索

使用

HTTP 错误处理

覆盖 RequestHandlerwrite_error(self, status_code, **kwargs) 方法即可,如:

class ErrorHandlerMixin:
  '''nicer error page'''
  error_page = '''\
<!DOCTYPE html>
<meta charset="utf-8" />
<title>%(code)s %(message)s</title>
<style type="text/css">
  body { font-family: serif; }
</style>
<h1>%(code)s %(message)s</h1>
<p>%(err)s</p>
<hr/>
'''

  def write_error(self, status_code, **kwargs):
    if self.settings.get("debug") and "exc_info" in kwargs:
      # in debug mode, try to send a traceback
      self.set_header('Content-Type', 'text/plain')
      for line in traceback.format_exception(*kwargs["exc_info"]):
        self.write(line)
      self.finish()
    else:
      err_exc = kwargs.get('exc_info', '  ')[1]
      if err_exc in (None, ' '):
        err_msg = ''
      else:
        if isinstance(err_exc, HTTPError):
          err_msg = str(err_exc.log_message) + '.'
        else:
          err_msg = str(err_exc) + '.'

      self.finish(self.error_page % {
        "code": status_code,
        "message": httpclient.responses[status_code],
        "err": err_msg,
      })

  @classmethod
  def patchHandler(cls, RequestHandler):
    '''patch a RequestHandler without subclassing

    In this way we can change all ``tornado.web.RequestHandler``. Simply
subclassing and replacing won't work due to the Python 2-style ``super()``
call in its ``__init__`` method.
    '''
    RequestHandler.write_error = cls.write_error
    RequestHandler.error_page = cls.error_page

注意

  • tornado.web.StaticFileHandler 会将整个文件读取到内存中再发送
  • tornado.autoreload 在重新执行时会丢失传给 Python 的参数,如 -u
  • RequestHandler.redirect 默认重定向地址不带域名。可手动加上:
import urllib.urlparse as urlparse
new_url = urlparse.urljoin(self.request.full_url(), new_url)

模板

默认 tornado.web.RequestHandlerrender 方法会压缩 .html 或者 .js 文件中的空白。如果不想这样做,可以更改模板文件的后缀,或者使用自定义的 tornado.template.Loader[1]

from tornado.template import Loader, Template

class MyLoader(Loader):
  def _create_template(self, name):
    path = os.path.join(self.root, name)
    f = open(path, "rb")
    template = Template(f.read(), name=name, loader=self,
                        compress_whitespace=False)  #  <--- 直接传入这个参数
    f.close()
    return template

template_path = './template'
tornado.web.Application(Handlers,
  template_path=template_path,
  template_loader = MyLoader(template_path),
)

配置

启用 debug 模式

Application 初始化时传递 debug=True

启用 gzip

Application 初始化时传递 gzip=True 。如需要修改使用 gzip 的文件类型,可修改 GZipContentEncoding 的属性 CONTENT_TYPES

tornado.web.GZipContentEncoding.CONTENT_TYPES.update(['application/javascript'])

在请求处理类中使用 self.settings.get("gzip") 来判断是否启用了 gzip。注意:如果设置了内容长度 Content-Length ,gzip 将会被禁用。

使用 HTTPS

设置必要的选项即可:[2]

app = Application()
http_server = tornado.httpserver.HTTPServer(
  app,
  ssl_options = {
    "certfile": os.path.expanduser("~/etc/key/server.crt"),
    "keyfile": os.path.expanduser("~/etc/key/server.key"),
  },
)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()

虚拟主机

使用 Application.add_handlers 方法时可指定主机名模式。此模式将从头匹配到尾(不含端口号)。

application.add_handlers(r'updl\.lilydjwg\.cjb\.net', [
  (r'/dl(?:/(.*)|$)', handlers.Download, {'dl_path': dl_path}),
  (r'/upload$', handlers.Upload, {
    'static_dir': static_dir,
    'upload_dir': upload_dir,
  }),
  (r'/static/(.*)', handlers.Upload, {'static_dir': static_dir}),
])

文档修改

修改 build/html/_static/default.css:126 ,设置已访问链接的颜色#551a8b

参见

外部链接

数据库

参考资料