|
|
@ -250,7 +250,7 @@ class RequestHandler(object): |
|
|
|
not self.request.connection.no_keep_alive): |
|
|
|
conn_header = self.request.headers.get("Connection") |
|
|
|
if conn_header and (conn_header.lower() == "keep-alive"): |
|
|
|
self.set_header("Connection", "Keep-Alive") |
|
|
|
self._headers["Connection"] = "Keep-Alive" |
|
|
|
self._write_buffer = [] |
|
|
|
self._status_code = 200 |
|
|
|
self._reason = httputil.responses[200] |
|
|
@ -348,12 +348,7 @@ class RequestHandler(object): |
|
|
|
|
|
|
|
The returned value is always unicode. |
|
|
|
""" |
|
|
|
args = self.get_arguments(name, strip=strip) |
|
|
|
if not args: |
|
|
|
if default is self._ARG_DEFAULT: |
|
|
|
raise MissingArgumentError(name) |
|
|
|
return default |
|
|
|
return args[-1] |
|
|
|
return self._get_argument(name, default, self.request.arguments, strip) |
|
|
|
|
|
|
|
def get_arguments(self, name, strip=True): |
|
|
|
"""Returns a list of the arguments with the given name. |
|
|
@ -362,9 +357,73 @@ class RequestHandler(object): |
|
|
|
|
|
|
|
The returned values are always unicode. |
|
|
|
""" |
|
|
|
return self._get_arguments(name, self.request.arguments, strip) |
|
|
|
|
|
|
|
def get_body_argument(self, name, default=_ARG_DEFAULT, strip=True): |
|
|
|
"""Returns the value of the argument with the given name |
|
|
|
from the request body. |
|
|
|
|
|
|
|
If default is not provided, the argument is considered to be |
|
|
|
required, and we raise a `MissingArgumentError` if it is missing. |
|
|
|
|
|
|
|
If the argument appears in the url more than once, we return the |
|
|
|
last value. |
|
|
|
|
|
|
|
The returned value is always unicode. |
|
|
|
|
|
|
|
.. versionadded:: 3.2 |
|
|
|
""" |
|
|
|
return self._get_argument(name, default, self.request.body_arguments, strip) |
|
|
|
|
|
|
|
def get_body_arguments(self, name, strip=True): |
|
|
|
"""Returns a list of the body arguments with the given name. |
|
|
|
|
|
|
|
If the argument is not present, returns an empty list. |
|
|
|
|
|
|
|
The returned values are always unicode. |
|
|
|
|
|
|
|
.. versionadded:: 3.2 |
|
|
|
""" |
|
|
|
return self._get_arguments(name, self.request.body_arguments, strip) |
|
|
|
|
|
|
|
def get_query_argument(self, name, default=_ARG_DEFAULT, strip=True): |
|
|
|
"""Returns the value of the argument with the given name |
|
|
|
from the request query string. |
|
|
|
|
|
|
|
If default is not provided, the argument is considered to be |
|
|
|
required, and we raise a `MissingArgumentError` if it is missing. |
|
|
|
|
|
|
|
If the argument appears in the url more than once, we return the |
|
|
|
last value. |
|
|
|
|
|
|
|
The returned value is always unicode. |
|
|
|
|
|
|
|
.. versionadded:: 3.2 |
|
|
|
""" |
|
|
|
return self._get_argument(name, default, self.request.query_arguments, strip) |
|
|
|
|
|
|
|
def get_query_arguments(self, name, strip=True): |
|
|
|
"""Returns a list of the query arguments with the given name. |
|
|
|
|
|
|
|
If the argument is not present, returns an empty list. |
|
|
|
|
|
|
|
The returned values are always unicode. |
|
|
|
|
|
|
|
.. versionadded:: 3.2 |
|
|
|
""" |
|
|
|
return self._get_arguments(name, self.request.query_arguments, strip) |
|
|
|
|
|
|
|
def _get_argument(self, name, default, source, strip=True): |
|
|
|
args = self._get_arguments(name, source, strip=strip) |
|
|
|
if not args: |
|
|
|
if default is self._ARG_DEFAULT: |
|
|
|
raise MissingArgumentError(name) |
|
|
|
return default |
|
|
|
return args[-1] |
|
|
|
|
|
|
|
def _get_arguments(self, name, source, strip=True): |
|
|
|
values = [] |
|
|
|
for v in self.request.arguments.get(name, []): |
|
|
|
for v in source.get(name, []): |
|
|
|
v = self.decode_argument(v, name=name) |
|
|
|
if isinstance(v, unicode_type): |
|
|
|
# Get rid of any weird control chars (unless decoding gave |
|
|
@ -838,7 +897,7 @@ class RequestHandler(object): |
|
|
|
else: |
|
|
|
self.finish(self.get_error_html(status_code, **kwargs)) |
|
|
|
return |
|
|
|
if self.settings.get("debug") and "exc_info" in kwargs: |
|
|
|
if self.settings.get("serve_traceback") 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"]): |
|
|
@ -1318,6 +1377,12 @@ def asynchronous(method): |
|
|
|
if not self._finished: |
|
|
|
self.finish() |
|
|
|
IOLoop.current().add_future(result, future_complete) |
|
|
|
# Once we have done this, hide the Future from our |
|
|
|
# caller (i.e. RequestHandler._when_complete), which |
|
|
|
# would otherwise set up its own callback and |
|
|
|
# exception handler (resulting in exceptions being |
|
|
|
# logged twice). |
|
|
|
return None |
|
|
|
return result |
|
|
|
return wrapper |
|
|
|
|
|
|
@ -1383,10 +1448,16 @@ class Application(object): |
|
|
|
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 an optional third element, which should be |
|
|
|
a dictionary if it is present. That dictionary is passed as |
|
|
|
keyword arguments to the contructor of the handler. This pattern |
|
|
|
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):: |
|
|
@ -1409,6 +1480,7 @@ class Application(object): |
|
|
|
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, |
|
|
|
wsgi=False, **settings): |
|
|
@ -1447,8 +1519,14 @@ class Application(object): |
|
|
|
if handlers: |
|
|
|
self.add_handlers(".*$", handlers) |
|
|
|
|
|
|
|
if self.settings.get('debug'): |
|
|
|
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("debug") and not wsgi: |
|
|
|
if self.settings.get('autoreload') and not wsgi: |
|
|
|
from tornado import autoreload |
|
|
|
autoreload.start() |
|
|
|
|
|
|
@ -1493,20 +1571,8 @@ class Application(object): |
|
|
|
|
|
|
|
for spec in host_handlers: |
|
|
|
if isinstance(spec, (tuple, list)): |
|
|
|
assert len(spec) in (2, 3) |
|
|
|
pattern = spec[0] |
|
|
|
handler = spec[1] |
|
|
|
|
|
|
|
if isinstance(handler, str): |
|
|
|
# import the Module and instantiate the class |
|
|
|
# Must be a fully qualified name (module.ClassName) |
|
|
|
handler = import_object(handler) |
|
|
|
|
|
|
|
if len(spec) == 3: |
|
|
|
kwargs = spec[2] |
|
|
|
else: |
|
|
|
kwargs = {} |
|
|
|
spec = URLSpec(pattern, handler, kwargs) |
|
|
|
assert len(spec) in (2, 3, 4) |
|
|
|
spec = URLSpec(*spec) |
|
|
|
handlers.append(spec) |
|
|
|
if spec.name: |
|
|
|
if spec.name in self.named_handlers: |
|
|
@ -1597,14 +1663,23 @@ class Application(object): |
|
|
|
args = [unquote(s) for s in match.groups()] |
|
|
|
break |
|
|
|
if not handler: |
|
|
|
handler = ErrorHandler(self, request, status_code=404) |
|
|
|
if self.settings.get('default_handler_class'): |
|
|
|
handler_class = self.settings['default_handler_class'] |
|
|
|
handler_args = self.settings.get( |
|
|
|
'default_handler_args', {}) |
|
|
|
else: |
|
|
|
handler_class = ErrorHandler |
|
|
|
handler_args = dict(status_code=404) |
|
|
|
handler = handler_class(self, request, **handler_args) |
|
|
|
|
|
|
|
# In debug mode, re-compile templates and reload static files on every |
|
|
|
# If template cache is disabled (usually in the debug mode), |
|
|
|
# re-compile templates and reload static files on every |
|
|
|
# request so you don't need to restart to see changes |
|
|
|
if self.settings.get("debug"): |
|
|
|
if not self.settings.get("compiled_template_cache", True): |
|
|
|
with RequestHandler._template_loader_lock: |
|
|
|
for loader in RequestHandler._template_loaders.values(): |
|
|
|
loader.reset() |
|
|
|
if not self.settings.get('static_hash_cache', True): |
|
|
|
StaticFileHandler.reset() |
|
|
|
|
|
|
|
handler._execute(transforms, *args, **kwargs) |
|
|
@ -2454,7 +2529,7 @@ class _UIModuleNamespace(object): |
|
|
|
|
|
|
|
class URLSpec(object): |
|
|
|
"""Specifies mappings between URLs and handlers.""" |
|
|
|
def __init__(self, pattern, handler_class, kwargs=None, name=None): |
|
|
|
def __init__(self, pattern, handler, kwargs=None, name=None): |
|
|
|
"""Parameters: |
|
|
|
|
|
|
|
* ``pattern``: Regular expression to be matched. Any groups |
|
|
@ -2475,7 +2550,13 @@ class URLSpec(object): |
|
|
|
assert len(self.regex.groupindex) in (0, self.regex.groups), \ |
|
|
|
("groups in url regexes must either be all named or all " |
|
|
|
"positional: %r" % self.regex.pattern) |
|
|
|
self.handler_class = handler_class |
|
|
|
|
|
|
|
if isinstance(handler, str): |
|
|
|
# import the Module and instantiate the class |
|
|
|
# Must be a fully qualified name (module.ClassName) |
|
|
|
handler = import_object(handler) |
|
|
|
|
|
|
|
self.handler_class = handler |
|
|
|
self.kwargs = kwargs or {} |
|
|
|
self.name = name |
|
|
|
self._path, self._group_count = self._find_groups() |
|
|
|