tornado框架源码---Application

tornado.web包含web框架的大部分主要功能,Application是其中一个重要的类

Application类的作用是实现 URI 转发,将 Application 的实例传递给 httpserver ,当监听到请求时,把服务器传回来的请求进行转发,通过调用 __call__ ,处理请求。

 

Application源码:

  1. class Application(httputil.HTTPServerConnectionDelegate):
  2. """A collection of request handlers that make up a web application.
  3. Instances of this class are callable and can be passed directly to
  4. HTTPServer to serve the application::
  5. application = web.Application([
  6. (r"/", MainPageHandler),
  7. ])
  8. http_server = httpserver.HTTPServer(application)
  9. http_server.listen(8080)
  10. ioloop.IOLoop.instance().start()
  11. The constructor for this class takes in a list of `URLSpec` objects
  12. or (regexp, request_class) tuples. When we receive requests, we
  13. iterate over the list in order and instantiate an instance of the
  14. first request class whose regexp matches the request path.
  15. The request class can be specified as either a class object or a
  16. (fully-qualified) name.
  17. Each tuple can contain additional elements, which correspond to the
  18. arguments to the `URLSpec` constructor. (Prior to Tornado 3.2, this
  19. only tuples of two or three elements were allowed).
  20. A dictionary may be passed as the third element of the tuple,
  21. which will be used as keyword arguments to the handler's
  22. constructor and `~RequestHandler.initialize` method. This pattern
  23. is used for the `StaticFileHandler` in this example (note that a
  24. `StaticFileHandler` can be installed automatically with the
  25. static_path setting described below)::
  26. application = web.Application([
  27. (r"/static/(.*)", web.StaticFileHandler, {"path": "/var/www"}),
  28. ])
  29. We support virtual hosts with the `add_handlers` method, which takes in
  30. a host regular expression as the first argument::
  31. application.add_handlers(r"www\.myhost\.com", [
  32. (r"/article/([0-9]+)", ArticleHandler),
  33. ])
  34. You can serve static files by sending the ``static_path`` setting
  35. as a keyword argument. We will serve those files from the
  36. ``/static/`` URI (this is configurable with the
  37. ``static_url_prefix`` setting), and we will serve ``/favicon.ico``
  38. and ``/robots.txt`` from the same directory. A custom subclass of
  39. `StaticFileHandler` can be specified with the
  40. ``static_handler_class`` setting.
  41. """
  42. def __init__(self, handlers=None, default_host="", transforms=None,
  43. **settings):
  44. if transforms is None:
  45. self.transforms = []
  46. if settings.get( "compress_response") or settings.get( "gzip"):
  47. self.transforms.append(GZipContentEncoding)
  48. else:
  49. self.transforms = transforms
  50. self.handlers = []
  51. self.named_handlers = {}
  52. self.default_host = default_host
  53. self.settings = settings
  54. self.ui_modules = { 'linkify': _linkify,
  55. 'xsrf_form_html': _xsrf_form_html,
  56. 'Template': TemplateModule,
  57. }
  58. self.ui_methods = {}
  59. self._load_ui_modules(settings.get( "ui_modules", {}))
  60. self._load_ui_methods(settings.get( "ui_methods", {}))
  61. if self.settings.get( "static_path"):
  62. path = self.settings[ "static_path"]
  63. handlers = list(handlers or [])
  64. static_url_prefix = settings.get( "static_url_prefix",
  65. "/static/")
  66. static_handler_class = settings.get( "static_handler_class",
  67. StaticFileHandler)
  68. static_handler_args = settings.get( "static_handler_args", {})
  69. static_handler_args[ 'path'] = path
  70. for pattern in [re.escape(static_url_prefix) + r"(.*)",
  71. r"/(favicon\.ico)", r"/(robots\.txt)"]:
  72. handlers.insert( 0, (pattern, static_handler_class,
  73. static_handler_args))
  74. if handlers:
  75. self.add_handlers( ".*$", handlers)
  76. if self.settings.get( 'debug'): # 如果debug = True, 开启autoreload 和 serve_traceback功能(出错显示错误信息), 关闭compiled_template_cache和static_hash_cache<span style="font-family: Arial, Helvetica, sans-serif;">功能</span>
  77. self.settings.setdefault( 'autoreload', True)
  78. self.settings.setdefault( 'compiled_template_cache', False)
  79. self.settings.setdefault( 'static_hash_cache', False)
  80. self.settings.setdefault( 'serve_traceback', True)
  81. # Automatically reload modified modules
  82. if self.settings.get( 'autoreload'): # 服务能够自动reload新的代码
  83. from tornado import autoreload
  84. autoreload.start()
  85. def listen(self, port, address="", **kwargs):
  86. """Starts an HTTP server for this application on the given port.
  87. This is a convenience alias for creating an `.HTTPServer`
  88. object and calling its listen method. Keyword arguments not
  89. supported by `HTTPServer.listen <.TCPServer.listen>` are passed to the
  90. `.HTTPServer` constructor. For advanced uses
  91. (e.g. multi-process mode), do not use this method; create an
  92. `.HTTPServer` and call its
  93. `.TCPServer.bind`/`.TCPServer.start` methods directly.
  94. Note that after calling this method you still need to call
  95. ``IOLoop.instance().start()`` to start the server.
  96. 接受端口,地址,其它参数
  97. 建立http服务器并监听该端口
  98. """
  99. # import is here rather than top level because HTTPServer
  100. # is not importable on appengine
  101. from tornado.httpserver import HTTPServer
  102. server = HTTPServer(self, **kwargs)
  103. server.listen(port, address)
  104. def add_handlers(self, host_pattern, host_handlers):
  105. """Appends the given handlers to our handler list.
  106. Host patterns are processed sequentially in the order they were
  107. added. All matching patterns will be considered.
  108. """
  109. if not host_pattern.endswith( "$"):
  110. host_pattern += "$"
  111. handlers = []
  112. # The handlers with the wildcard host_pattern are a special
  113. # case - they're added in the constructor but should have lower
  114. # precedence than the more-precise handlers added later.
  115. # If a wildcard handler group exists, it should always be last
  116. # in the list, so insert new groups just before it.
  117. if self.handlers and self.handlers[ -1][ 0].pattern == '.*$':
  118. self.handlers.insert( -1, (re.compile(host_pattern), handlers))
  119. else:
  120. self.handlers.append((re.compile(host_pattern), handlers))
  121. for spec in host_handlers:
  122. if isinstance(spec, (tuple, list)):
  123. assert len(spec) in ( 2, 3, 4)
  124. spec = URLSpec(*spec)
  125. handlers.append(spec)
  126. if spec.name:
  127. if spec.name in self.named_handlers:
  128. app_log.warning(
  129. "Multiple handlers named %s; replacing previous value",
  130. spec.name)
  131. self.named_handlers[spec.name] = spec
  132. def add_transform(self, transform_class):
  133. self.transforms.append(transform_class)
  134. def _get_host_handlers(self, request):
  135. host = request.host.lower().split( ':')[ 0]
  136. matches = []
  137. for pattern, handlers in self.handlers:
  138. if pattern.match(host):
  139. matches.extend(handlers)
  140. # Look for default host if not behind load balancer (for debugging)
  141. if not matches and "X-Real-Ip" not in request.headers:
  142. for pattern, handlers in self.handlers:
  143. if pattern.match(self.default_host):
  144. matches.extend(handlers)
  145. return matches or None
  146. def _load_ui_methods(self, methods):
  147. if isinstance(methods, types.ModuleType):
  148. self._load_ui_methods(dict((n, getattr(methods, n))
  149. for n in dir(methods)))
  150. elif isinstance(methods, list):
  151. for m in methods:
  152. self._load_ui_methods(m)
  153. else:
  154. for name, fn in methods.items():
  155. if not name.startswith( "_") and hasattr(fn, "__call__") \
  156. and name[ 0].lower() == name[ 0]:
  157. self.ui_methods[name] = fn
  158. def _load_ui_modules(self, modules):
  159. if isinstance(modules, types.ModuleType):
  160. self._load_ui_modules(dict((n, getattr(modules, n))
  161. for n in dir(modules)))
  162. elif isinstance(modules, list):
  163. for m in modules:
  164. self._load_ui_modules(m)
  165. else:
  166. assert isinstance(modules, dict)
  167. for name, cls in modules.items():
  168. try:
  169. if issubclass(cls, UIModule):
  170. self.ui_modules[name] = cls
  171. except TypeError:
  172. pass
  173. def start_request(self, connection):
  174. # Modern HTTPServer interface
  175. return _RequestDispatcher(self, connection)
  176. def __call__(self, request):
  177. # Legacy HTTPServer interface
  178. dispatcher = _RequestDispatcher(self, None)
  179. dispatcher.set_request(request)
  180. return dispatcher.execute()
  181. def reverse_url(self, name, *args):
  182. """Returns a URL path for handler named ``name``
  183. The handler must be added to the application as a named `URLSpec`.
  184. Args will be substituted for capturing groups in the `URLSpec` regex.
  185. They will be converted to strings if necessary, encoded as utf8,
  186. and url-escaped.
  187. 根据name返回匹配的url路径
  188. """
  189. if name in self.named_handlers:
  190. return self.named_handlers[name].reverse(*args)
  191. raise KeyError( "%s not found in named urls" % name)
  192. def log_request(self, handler):
  193. """Writes a completed HTTP request to the logs.
  194. By default writes to the python root logger. To change
  195. this behavior either subclass Application and override this method,
  196. or pass a function in the application settings dictionary as
  197. ``log_function``.
  198. 把HTTP请求写进日志
  199. http状态码小于400的为正常
  200. 大于等于400小于500<span style="font-family: Arial, Helvetica, sans-serif;">为</span><span style="font-family: Arial, Helvetica, sans-serif;">请求错误</span>
  201. 大于500是服务器错误
  202. """
  203. if "log_function" in self.settings:
  204. self.settings[ "log_function"](handler)
  205. return
  206. if handler.get_status() < 400:
  207. log_method = access_log.info
  208. elif handler.get_status() < 500:
  209. log_method = access_log.warning
  210. else:
  211. log_method = access_log.error
  212. request_time = 1000.0 * handler.request.request_time()
  213. log_method( "%d %s %.2fms", handler.get_status(),
  214. handler._request_summary(), request_time)



构造函数

__init__(self,handlers=None,default_host="",transforms=None,**settings)  

它接受handlers (包含匹配规则和requesthandler的元组),default_host(默认主机),transforms(输出做分块和压缩的转换)和setting(包含配置的字典)。

建立主机的路径路由规则

 

方法

listen(self, port, address="", **kwargs) 建立http服务器并监听该端口

add_handlers(self, host_pattern, host_handlers)向handler列表中添加handler。host_pattern依次按照它们的添加顺序进行处理,添加主机的路径路由规则

add_transform(self, transform_class)向self.transforms增加transform_class,对输出做分块和压缩的转换

_get_host_handlers(self, request)寻找属于这个request的handlers

_load_ui_methods(self, methods)在self.ui_methods中添加方法

_load_ui_modules(self, modules)在self.ui_modules中添加方法

reverse_url(self, name, *args)使用name返回匹配的url路径

__call__(self, request) 在服务器接受新连接时被调用 接受HttpRequest对象 根据 httprequest 调用execute 方法

start_request(self, connection)作用同__call__

log_request(self, handler)把HTTP请求写进日志。


debug=True 时代码动态自动编译的原理

Application 对象实例化时,给出“debug=True”参数的话,开启autoreload 和 serve_traceback功能(出错显示错误信息) , 关闭compiled_template_cache和static_hash_cache功能  


autoreload:改变源代码的时候,服务器进程将能够自动reload新的代码并重启。

serve_traceback:如果开启,在出错的时候就不是返回默认的错误页面,取而代之的是显示python的traceback,利用这个我们可以看到在什么地方出现了错误,可以进行方便的调试

compiled_template_cache:编译模板缓存,如果关闭,在刷新时服务器的模板都会重新加载

static_hash_cache:静态哈希缓存如果关闭,在刷新时有static_url()的地方都会重新载入需要读取的static下的文件,而不是用已经缓存了的文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值