tornado.web包含web框架的大部分主要功能,Application是其中一个重要的类
Application类的作用是实现 URI 转发,将 Application 的实例传递给 httpserver ,当监听到请求时,把服务器传回来的请求进行转发,通过调用 __call__ ,处理请求。
Application源码:
-
class Application(httputil.HTTPServerConnectionDelegate):
-
"""A collection of request handlers that make up a web application.
-
-
Instances of this class are callable and can be passed directly to
-
HTTPServer to serve the application::
-
-
application = web.Application([
-
(r"/", MainPageHandler),
-
])
-
http_server = httpserver.HTTPServer(application)
-
http_server.listen(8080)
-
ioloop.IOLoop.instance().start()
-
-
The constructor for this class takes in a list of `URLSpec` objects
-
or (regexp, request_class) tuples. When we receive requests, we
-
iterate over the list in order and instantiate an instance of the
-
first request class whose regexp matches the request path.
-
The request class can be specified as either a class object or a
-
(fully-qualified) name.
-
-
Each tuple can contain additional elements, which correspond to the
-
arguments to the `URLSpec` constructor. (Prior to Tornado 3.2, this
-
only tuples of two or three elements were allowed).
-
-
A dictionary may be passed as the third element of the tuple,
-
which will be used as keyword arguments to the handler's
-
constructor and `~RequestHandler.initialize` method. This pattern
-
is used for the `StaticFileHandler` in this example (note that a
-
`StaticFileHandler` can be installed automatically with the
-
static_path setting described below)::
-
-
application = web.Application([
-
(r"/static/(.*)", web.StaticFileHandler, {"path": "/var/www"}),
-
])
-
-
We support virtual hosts with the `add_handlers` method, which takes in
-
a host regular expression as the first argument::
-
-
application.add_handlers(r"www\.myhost\.com", [
-
(r"/article/([0-9]+)", ArticleHandler),
-
])
-
-
You can serve static files by sending the ``static_path`` setting
-
as a keyword argument. We will serve those files from the
-
``/static/`` URI (this is configurable with the
-
``static_url_prefix`` setting), and we will serve ``/favicon.ico``
-
and ``/robots.txt`` from the same directory. A custom subclass of
-
`StaticFileHandler` can be specified with the
-
``static_handler_class`` setting.
-
-
"""
-
def __init__(self, handlers=None, default_host="", transforms=None,
-
**settings):
-
if transforms is None:
-
self.transforms = []
-
if settings.get( "compress_response") or settings.get( "gzip"):
-
self.transforms.append(GZipContentEncoding)
-
else:
-
self.transforms = transforms
-
self.handlers = []
-
self.named_handlers = {}
-
self.default_host = default_host
-
self.settings = settings
-
self.ui_modules = { 'linkify': _linkify,
-
'xsrf_form_html': _xsrf_form_html,
-
'Template': TemplateModule,
-
}
-
self.ui_methods = {}
-
self._load_ui_modules(settings.get( "ui_modules", {}))
-
self._load_ui_methods(settings.get( "ui_methods", {}))
-
if self.settings.get( "static_path"):
-
path = self.settings[ "static_path"]
-
handlers = list(handlers or [])
-
static_url_prefix = settings.get( "static_url_prefix",
-
"/static/")
-
static_handler_class = settings.get( "static_handler_class",
-
StaticFileHandler)
-
static_handler_args = settings.get( "static_handler_args", {})
-
static_handler_args[ 'path'] = path
-
for pattern in [re.escape(static_url_prefix) + r"(.*)",
-
r"/(favicon\.ico)", r"/(robots\.txt)"]:
-
handlers.insert( 0, (pattern, static_handler_class,
-
static_handler_args))
-
if handlers:
-
self.add_handlers( ".*$", handlers)
-
-
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>
-
-
self.settings.setdefault( 'autoreload', True)
-
self.settings.setdefault( 'compiled_template_cache', False)
-
self.settings.setdefault( 'static_hash_cache', False)
-
self.settings.setdefault( 'serve_traceback', True)
-
-
# Automatically reload modified modules
-
if self.settings.get( 'autoreload'): # 服务能够自动reload新的代码
-
from tornado import autoreload
-
autoreload.start()
-
-
def listen(self, port, address="", **kwargs):
-
"""Starts an HTTP server for this application on the given port.
-
-
This is a convenience alias for creating an `.HTTPServer`
-
object and calling its listen method. Keyword arguments not
-
supported by `HTTPServer.listen <.TCPServer.listen>` are passed to the
-
`.HTTPServer` constructor. For advanced uses
-
(e.g. multi-process mode), do not use this method; create an
-
`.HTTPServer` and call its
-
`.TCPServer.bind`/`.TCPServer.start` methods directly.
-
-
Note that after calling this method you still need to call
-
``IOLoop.instance().start()`` to start the server.
-
接受端口,地址,其它参数
-
建立http服务器并监听该端口
-
"""
-
# import is here rather than top level because HTTPServer
-
# is not importable on appengine
-
from tornado.httpserver import HTTPServer
-
server = HTTPServer(self, **kwargs)
-
server.listen(port, address)
-
-
def add_handlers(self, host_pattern, host_handlers):
-
"""Appends the given handlers to our handler list.
-
-
Host patterns are processed sequentially in the order they were
-
added. All matching patterns will be considered.
-
"""
-
if not host_pattern.endswith( "$"):
-
host_pattern += "$"
-
handlers = []
-
# The handlers with the wildcard host_pattern are a special
-
# case - they're added in the constructor but should have lower
-
# precedence than the more-precise handlers added later.
-
# If a wildcard handler group exists, it should always be last
-
# in the list, so insert new groups just before it.
-
if self.handlers and self.handlers[ -1][ 0].pattern == '.*$':
-
self.handlers.insert( -1, (re.compile(host_pattern), handlers))
-
else:
-
self.handlers.append((re.compile(host_pattern), handlers))
-
-
for spec in host_handlers:
-
if isinstance(spec, (tuple, list)):
-
assert len(spec) in ( 2, 3, 4)
-
spec = URLSpec(*spec)
-
handlers.append(spec)
-
if spec.name:
-
if spec.name in self.named_handlers:
-
app_log.warning(
-
"Multiple handlers named %s; replacing previous value",
-
spec.name)
-
self.named_handlers[spec.name] = spec
-
-
def add_transform(self, transform_class):
-
self.transforms.append(transform_class)
-
-
def _get_host_handlers(self, request):
-
host = request.host.lower().split( ':')[ 0]
-
matches = []
-
for pattern, handlers in self.handlers:
-
if pattern.match(host):
-
matches.extend(handlers)
-
# Look for default host if not behind load balancer (for debugging)
-
if not matches and "X-Real-Ip" not in request.headers:
-
for pattern, handlers in self.handlers:
-
if pattern.match(self.default_host):
-
matches.extend(handlers)
-
return matches or None
-
-
def _load_ui_methods(self, methods):
-
if isinstance(methods, types.ModuleType):
-
self._load_ui_methods(dict((n, getattr(methods, n))
-
for n in dir(methods)))
-
elif isinstance(methods, list):
-
for m in methods:
-
self._load_ui_methods(m)
-
else:
-
for name, fn in methods.items():
-
if not name.startswith( "_") and hasattr(fn, "__call__") \
-
and name[ 0].lower() == name[ 0]:
-
self.ui_methods[name] = fn
-
-
def _load_ui_modules(self, modules):
-
if isinstance(modules, types.ModuleType):
-
self._load_ui_modules(dict((n, getattr(modules, n))
-
for n in dir(modules)))
-
elif isinstance(modules, list):
-
for m in modules:
-
self._load_ui_modules(m)
-
else:
-
assert isinstance(modules, dict)
-
for name, cls in modules.items():
-
try:
-
if issubclass(cls, UIModule):
-
self.ui_modules[name] = cls
-
except TypeError:
-
pass
-
-
def start_request(self, connection):
-
# Modern HTTPServer interface
-
return _RequestDispatcher(self, connection)
-
-
def __call__(self, request):
-
# Legacy HTTPServer interface
-
dispatcher = _RequestDispatcher(self, None)
-
dispatcher.set_request(request)
-
return dispatcher.execute()
-
-
def reverse_url(self, name, *args):
-
"""Returns a URL path for handler named ``name``
-
-
The handler must be added to the application as a named `URLSpec`.
-
-
Args will be substituted for capturing groups in the `URLSpec` regex.
-
They will be converted to strings if necessary, encoded as utf8,
-
and url-escaped.
-
根据name返回匹配的url路径
-
"""
-
if name in self.named_handlers:
-
return self.named_handlers[name].reverse(*args)
-
raise KeyError( "%s not found in named urls" % name)
-
-
def log_request(self, handler):
-
"""Writes a completed HTTP request to the logs.
-
-
By default writes to the python root logger. To change
-
this behavior either subclass Application and override this method,
-
or pass a function in the application settings dictionary as
-
``log_function``.
-
把HTTP请求写进日志
-
http状态码小于400的为正常
-
大于等于400小于500<span style="font-family: Arial, Helvetica, sans-serif;">为</span><span style="font-family: Arial, Helvetica, sans-serif;">请求错误</span>
-
大于500是服务器错误
-
"""
-
if "log_function" in self.settings:
-
self.settings[ "log_function"](handler)
-
return
-
if handler.get_status() < 400:
-
log_method = access_log.info
-
elif handler.get_status() < 500:
-
log_method = access_log.warning
-
else:
-
log_method = access_log.error
-
request_time = 1000.0 * handler.request.request_time()
-
log_method( "%d %s %.2fms", handler.get_status(),
-
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下的文件,而不是用已经缓存了的文件。