|
|
@ -340,7 +340,7 @@ class RequestHandler(object): |
|
|
|
""" |
|
|
|
pass |
|
|
|
|
|
|
|
def set_status(self, status_code: int, reason: Optional[str] = None) -> None: |
|
|
|
def set_status(self, status_code: int, reason: str = None) -> None: |
|
|
|
"""Sets the status code for our response. |
|
|
|
|
|
|
|
:arg int status_code: Response status code. |
|
|
@ -424,14 +424,14 @@ class RequestHandler(object): |
|
|
|
def get_argument(self, name: str, default: str, strip: bool = True) -> str: |
|
|
|
pass |
|
|
|
|
|
|
|
@overload |
|
|
|
def get_argument( # noqa: F811 |
|
|
|
@overload # noqa: F811 |
|
|
|
def get_argument( |
|
|
|
self, name: str, default: _ArgDefaultMarker = _ARG_DEFAULT, strip: bool = True |
|
|
|
) -> str: |
|
|
|
pass |
|
|
|
|
|
|
|
@overload |
|
|
|
def get_argument( # noqa: F811 |
|
|
|
@overload # noqa: F811 |
|
|
|
def get_argument( |
|
|
|
self, name: str, default: None, strip: bool = True |
|
|
|
) -> Optional[str]: |
|
|
|
pass |
|
|
@ -554,7 +554,7 @@ class RequestHandler(object): |
|
|
|
values.append(s) |
|
|
|
return values |
|
|
|
|
|
|
|
def decode_argument(self, value: bytes, name: Optional[str] = None) -> str: |
|
|
|
def decode_argument(self, value: bytes, name: str = None) -> str: |
|
|
|
"""Decodes an argument from the request. |
|
|
|
|
|
|
|
The argument has been percent-decoded and is now a byte string. |
|
|
@ -580,7 +580,7 @@ class RequestHandler(object): |
|
|
|
`self.request.cookies <.httputil.HTTPServerRequest.cookies>`.""" |
|
|
|
return self.request.cookies |
|
|
|
|
|
|
|
def get_cookie(self, name: str, default: Optional[str] = None) -> Optional[str]: |
|
|
|
def get_cookie(self, name: str, default: str = None) -> Optional[str]: |
|
|
|
"""Returns the value of the request cookie with the given name. |
|
|
|
|
|
|
|
If the named cookie is not present, returns ``default``. |
|
|
@ -597,10 +597,10 @@ class RequestHandler(object): |
|
|
|
self, |
|
|
|
name: str, |
|
|
|
value: Union[str, bytes], |
|
|
|
domain: Optional[str] = None, |
|
|
|
expires: Optional[Union[float, Tuple, datetime.datetime]] = None, |
|
|
|
domain: str = None, |
|
|
|
expires: Union[float, Tuple, datetime.datetime] = None, |
|
|
|
path: str = "/", |
|
|
|
expires_days: Optional[int] = None, |
|
|
|
expires_days: int = None, |
|
|
|
**kwargs: Any |
|
|
|
) -> None: |
|
|
|
"""Sets an outgoing cookie name/value with the given options. |
|
|
@ -624,9 +624,7 @@ class RequestHandler(object): |
|
|
|
# Don't let us accidentally inject bad stuff |
|
|
|
raise ValueError("Invalid cookie %r: %r" % (name, value)) |
|
|
|
if not hasattr(self, "_new_cookie"): |
|
|
|
self._new_cookie = ( |
|
|
|
http.cookies.SimpleCookie() |
|
|
|
) # type: http.cookies.SimpleCookie |
|
|
|
self._new_cookie = http.cookies.SimpleCookie() |
|
|
|
if name in self._new_cookie: |
|
|
|
del self._new_cookie[name] |
|
|
|
self._new_cookie[name] = value |
|
|
@ -650,9 +648,7 @@ class RequestHandler(object): |
|
|
|
|
|
|
|
morsel[k] = v |
|
|
|
|
|
|
|
def clear_cookie( |
|
|
|
self, name: str, path: str = "/", domain: Optional[str] = None |
|
|
|
) -> None: |
|
|
|
def clear_cookie(self, name: str, path: str = "/", domain: str = None) -> None: |
|
|
|
"""Deletes the cookie with the given name. |
|
|
|
|
|
|
|
Due to limitations of the cookie protocol, you must pass the same |
|
|
@ -666,7 +662,7 @@ class RequestHandler(object): |
|
|
|
expires = datetime.datetime.utcnow() - datetime.timedelta(days=365) |
|
|
|
self.set_cookie(name, value="", path=path, expires=expires, domain=domain) |
|
|
|
|
|
|
|
def clear_all_cookies(self, path: str = "/", domain: Optional[str] = None) -> None: |
|
|
|
def clear_all_cookies(self, path: str = "/", domain: str = None) -> None: |
|
|
|
"""Deletes all the cookies the user sent with this request. |
|
|
|
|
|
|
|
See `clear_cookie` for more information on the path and domain |
|
|
@ -686,8 +682,8 @@ class RequestHandler(object): |
|
|
|
self, |
|
|
|
name: str, |
|
|
|
value: Union[str, bytes], |
|
|
|
expires_days: Optional[int] = 30, |
|
|
|
version: Optional[int] = None, |
|
|
|
expires_days: int = 30, |
|
|
|
version: int = None, |
|
|
|
**kwargs: Any |
|
|
|
) -> None: |
|
|
|
"""Signs and timestamps a cookie so it cannot be forged. |
|
|
@ -701,7 +697,6 @@ class RequestHandler(object): |
|
|
|
Note that the ``expires_days`` parameter sets the lifetime of the |
|
|
|
cookie in the browser, but is independent of the ``max_age_days`` |
|
|
|
parameter to `get_secure_cookie`. |
|
|
|
A value of None limits the lifetime to the current browser session. |
|
|
|
|
|
|
|
Secure cookies may contain arbitrary byte values, not just unicode |
|
|
|
strings (unlike regular cookies) |
|
|
@ -722,7 +717,7 @@ class RequestHandler(object): |
|
|
|
) |
|
|
|
|
|
|
|
def create_signed_value( |
|
|
|
self, name: str, value: Union[str, bytes], version: Optional[int] = None |
|
|
|
self, name: str, value: Union[str, bytes], version: int = None |
|
|
|
) -> bytes: |
|
|
|
"""Signs and timestamps a string so it cannot be forged. |
|
|
|
|
|
|
@ -750,9 +745,9 @@ class RequestHandler(object): |
|
|
|
def get_secure_cookie( |
|
|
|
self, |
|
|
|
name: str, |
|
|
|
value: Optional[str] = None, |
|
|
|
value: str = None, |
|
|
|
max_age_days: int = 31, |
|
|
|
min_version: Optional[int] = None, |
|
|
|
min_version: int = None, |
|
|
|
) -> Optional[bytes]: |
|
|
|
"""Returns the given signed cookie if it validates, or None. |
|
|
|
|
|
|
@ -780,7 +775,7 @@ class RequestHandler(object): |
|
|
|
) |
|
|
|
|
|
|
|
def get_secure_cookie_key_version( |
|
|
|
self, name: str, value: Optional[str] = None |
|
|
|
self, name: str, value: str = None |
|
|
|
) -> Optional[int]: |
|
|
|
"""Returns the signing key version of the secure cookie. |
|
|
|
|
|
|
@ -793,9 +788,7 @@ class RequestHandler(object): |
|
|
|
return None |
|
|
|
return get_signature_key_version(value) |
|
|
|
|
|
|
|
def redirect( |
|
|
|
self, url: str, permanent: bool = False, status: Optional[int] = None |
|
|
|
) -> None: |
|
|
|
def redirect(self, url: str, permanent: bool = False, status: int = None) -> None: |
|
|
|
"""Sends a redirect to the given (optionally relative) URL. |
|
|
|
|
|
|
|
If the ``status`` argument is specified, that value is used as the |
|
|
@ -1058,6 +1051,12 @@ class RequestHandler(object): |
|
|
|
def flush(self, include_footers: bool = False) -> "Future[None]": |
|
|
|
"""Flushes the current output buffer to the network. |
|
|
|
|
|
|
|
The ``callback`` argument, if given, can be used for flow control: |
|
|
|
it will be run when all flushed data has been written to the socket. |
|
|
|
Note that only one flush callback can be outstanding at a time; |
|
|
|
if another flush occurs before the previous flush's callback |
|
|
|
has been run, the previous callback will be discarded. |
|
|
|
|
|
|
|
.. versionchanged:: 4.0 |
|
|
|
Now returns a `.Future` if no callback is given. |
|
|
|
|
|
|
@ -1105,7 +1104,7 @@ class RequestHandler(object): |
|
|
|
future.set_result(None) |
|
|
|
return future |
|
|
|
|
|
|
|
def finish(self, chunk: Optional[Union[str, bytes, dict]] = None) -> "Future[None]": |
|
|
|
def finish(self, chunk: Union[str, bytes, dict] = None) -> "Future[None]": |
|
|
|
"""Finishes this response, ending the HTTP request. |
|
|
|
|
|
|
|
Passing a ``chunk`` to ``finish()`` is equivalent to passing that |
|
|
@ -1138,11 +1137,13 @@ class RequestHandler(object): |
|
|
|
if self.check_etag_header(): |
|
|
|
self._write_buffer = [] |
|
|
|
self.set_status(304) |
|
|
|
if self._status_code in (204, 304) or (100 <= self._status_code < 200): |
|
|
|
if self._status_code in (204, 304) or ( |
|
|
|
self._status_code >= 100 and self._status_code < 200 |
|
|
|
): |
|
|
|
assert not self._write_buffer, ( |
|
|
|
"Cannot send body with %s" % self._status_code |
|
|
|
) |
|
|
|
self._clear_representation_headers() |
|
|
|
self._clear_headers_for_304() |
|
|
|
elif "Content-Length" not in self._headers: |
|
|
|
content_length = sum(len(part) for part in self._write_buffer) |
|
|
|
self.set_header("Content-Length", content_length) |
|
|
@ -1543,9 +1544,7 @@ class RequestHandler(object): |
|
|
|
+ '"/>' |
|
|
|
) |
|
|
|
|
|
|
|
def static_url( |
|
|
|
self, path: str, include_host: Optional[bool] = None, **kwargs: Any |
|
|
|
) -> str: |
|
|
|
def static_url(self, path: str, include_host: bool = None, **kwargs: Any) -> str: |
|
|
|
"""Returns a static URL for the given relative static file path. |
|
|
|
|
|
|
|
This method requires you set the ``static_path`` setting in your |
|
|
@ -1786,11 +1785,11 @@ class RequestHandler(object): |
|
|
|
args = [value.status_code, self._request_summary()] + list(value.args) |
|
|
|
gen_log.warning(format, *args) |
|
|
|
else: |
|
|
|
app_log.error( |
|
|
|
app_log.error( # type: ignore |
|
|
|
"Uncaught exception %s\n%r", |
|
|
|
self._request_summary(), |
|
|
|
self.request, |
|
|
|
exc_info=(typ, value, tb), # type: ignore |
|
|
|
exc_info=(typ, value, tb), |
|
|
|
) |
|
|
|
|
|
|
|
def _ui_module(self, name: str, module: Type["UIModule"]) -> Callable[..., str]: |
|
|
@ -1807,13 +1806,21 @@ class RequestHandler(object): |
|
|
|
def _ui_method(self, method: Callable[..., str]) -> Callable[..., str]: |
|
|
|
return lambda *args, **kwargs: method(self, *args, **kwargs) |
|
|
|
|
|
|
|
def _clear_representation_headers(self) -> None: |
|
|
|
# 304 responses should not contain representation metadata |
|
|
|
# headers (defined in |
|
|
|
# https://tools.ietf.org/html/rfc7231#section-3.1) |
|
|
|
def _clear_headers_for_304(self) -> None: |
|
|
|
# 304 responses should not contain entity headers (defined in |
|
|
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.1) |
|
|
|
# not explicitly allowed by |
|
|
|
# https://tools.ietf.org/html/rfc7232#section-4.1 |
|
|
|
headers = ["Content-Encoding", "Content-Language", "Content-Type"] |
|
|
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5 |
|
|
|
headers = [ |
|
|
|
"Allow", |
|
|
|
"Content-Encoding", |
|
|
|
"Content-Language", |
|
|
|
"Content-Length", |
|
|
|
"Content-MD5", |
|
|
|
"Content-Range", |
|
|
|
"Content-Type", |
|
|
|
"Last-Modified", |
|
|
|
] |
|
|
|
for h in headers: |
|
|
|
self.clear_header(h) |
|
|
|
|
|
|
@ -1918,9 +1925,7 @@ class _ApplicationRouter(ReversibleRuleRouter): |
|
|
|
`_ApplicationRouter` instance. |
|
|
|
""" |
|
|
|
|
|
|
|
def __init__( |
|
|
|
self, application: "Application", rules: Optional[_RuleList] = None |
|
|
|
) -> None: |
|
|
|
def __init__(self, application: "Application", rules: _RuleList = None) -> None: |
|
|
|
assert isinstance(application, Application) |
|
|
|
self.application = application |
|
|
|
super(_ApplicationRouter, self).__init__(rules) |
|
|
@ -1929,8 +1934,8 @@ class _ApplicationRouter(ReversibleRuleRouter): |
|
|
|
rule = super(_ApplicationRouter, self).process_rule(rule) |
|
|
|
|
|
|
|
if isinstance(rule.target, (list, tuple)): |
|
|
|
rule.target = _ApplicationRouter( |
|
|
|
self.application, rule.target # type: ignore |
|
|
|
rule.target = _ApplicationRouter( # type: ignore |
|
|
|
self.application, rule.target |
|
|
|
) |
|
|
|
|
|
|
|
return rule |
|
|
@ -2034,9 +2039,9 @@ class Application(ReversibleRouter): |
|
|
|
|
|
|
|
def __init__( |
|
|
|
self, |
|
|
|
handlers: Optional[_RuleList] = None, |
|
|
|
default_host: Optional[str] = None, |
|
|
|
transforms: Optional[List[Type["OutputTransform"]]] = None, |
|
|
|
handlers: _RuleList = None, |
|
|
|
default_host: str = None, |
|
|
|
transforms: List[Type["OutputTransform"]] = None, |
|
|
|
**settings: Any |
|
|
|
) -> None: |
|
|
|
if transforms is None: |
|
|
@ -2187,9 +2192,9 @@ class Application(ReversibleRouter): |
|
|
|
self, |
|
|
|
request: httputil.HTTPServerRequest, |
|
|
|
target_class: Type[RequestHandler], |
|
|
|
target_kwargs: Optional[Dict[str, Any]] = None, |
|
|
|
path_args: Optional[List[bytes]] = None, |
|
|
|
path_kwargs: Optional[Dict[str, bytes]] = None, |
|
|
|
target_kwargs: Dict[str, Any] = None, |
|
|
|
path_args: List[bytes] = None, |
|
|
|
path_kwargs: Dict[str, bytes] = None, |
|
|
|
) -> "_HandlerDelegate": |
|
|
|
"""Returns `~.httputil.HTTPMessageDelegate` that can serve a request |
|
|
|
for application and `RequestHandler` subclass. |
|
|
@ -2356,11 +2361,7 @@ class HTTPError(Exception): |
|
|
|
""" |
|
|
|
|
|
|
|
def __init__( |
|
|
|
self, |
|
|
|
status_code: int = 500, |
|
|
|
log_message: Optional[str] = None, |
|
|
|
*args: Any, |
|
|
|
**kwargs: Any |
|
|
|
self, status_code: int = 500, log_message: str = None, *args: Any, **kwargs: Any |
|
|
|
) -> None: |
|
|
|
self.status_code = status_code |
|
|
|
self.log_message = log_message |
|
|
@ -2477,8 +2478,8 @@ class RedirectHandler(RequestHandler): |
|
|
|
self._url = url |
|
|
|
self._permanent = permanent |
|
|
|
|
|
|
|
def get(self, *args: Any, **kwargs: Any) -> None: |
|
|
|
to_url = self._url.format(*args, **kwargs) |
|
|
|
def get(self, *args: Any) -> None: |
|
|
|
to_url = self._url.format(*args) |
|
|
|
if self.request.query_arguments: |
|
|
|
# TODO: figure out typing for the next line. |
|
|
|
to_url = httputil.url_concat( |
|
|
@ -2560,7 +2561,7 @@ class StaticFileHandler(RequestHandler): |
|
|
|
_static_hashes = {} # type: Dict[str, Optional[str]] |
|
|
|
_lock = threading.Lock() # protects _static_hashes |
|
|
|
|
|
|
|
def initialize(self, path: str, default_filename: Optional[str] = None) -> None: |
|
|
|
def initialize(self, path: str, default_filename: str = None) -> None: |
|
|
|
self.root = path |
|
|
|
self.default_filename = default_filename |
|
|
|
|
|
|
@ -2786,7 +2787,7 @@ class StaticFileHandler(RequestHandler): |
|
|
|
|
|
|
|
@classmethod |
|
|
|
def get_content( |
|
|
|
cls, abspath: str, start: Optional[int] = None, end: Optional[int] = None |
|
|
|
cls, abspath: str, start: int = None, end: int = None |
|
|
|
) -> Generator[bytes, None, None]: |
|
|
|
"""Retrieve the content of the requested resource which is located |
|
|
|
at the given absolute path. |
|
|
@ -2828,12 +2829,12 @@ class StaticFileHandler(RequestHandler): |
|
|
|
"""Returns a version string for the resource at the given path. |
|
|
|
|
|
|
|
This class method may be overridden by subclasses. The |
|
|
|
default implementation is a SHA-512 hash of the file's contents. |
|
|
|
default implementation is a hash of the file's contents. |
|
|
|
|
|
|
|
.. versionadded:: 3.1 |
|
|
|
""" |
|
|
|
data = cls.get_content(abspath) |
|
|
|
hasher = hashlib.sha512() |
|
|
|
hasher = hashlib.md5() |
|
|
|
if isinstance(data, bytes): |
|
|
|
hasher.update(data) |
|
|
|
else: |
|
|
@ -3350,9 +3351,9 @@ def create_signed_value( |
|
|
|
secret: _CookieSecretTypes, |
|
|
|
name: str, |
|
|
|
value: Union[str, bytes], |
|
|
|
version: Optional[int] = None, |
|
|
|
clock: Optional[Callable[[], float]] = None, |
|
|
|
key_version: Optional[int] = None, |
|
|
|
version: int = None, |
|
|
|
clock: Callable[[], float] = None, |
|
|
|
key_version: int = None, |
|
|
|
) -> bytes: |
|
|
|
if version is None: |
|
|
|
version = DEFAULT_SIGNED_VALUE_VERSION |
|
|
@ -3441,8 +3442,8 @@ def decode_signed_value( |
|
|
|
name: str, |
|
|
|
value: Union[None, str, bytes], |
|
|
|
max_age_days: int = 31, |
|
|
|
clock: Optional[Callable[[], float]] = None, |
|
|
|
min_version: Optional[int] = None, |
|
|
|
clock: Callable[[], float] = None, |
|
|
|
min_version: int = None, |
|
|
|
) -> Optional[bytes]: |
|
|
|
if clock is None: |
|
|
|
clock = time.time |
|
|
|