import logging
import os
import socket
+import sys
import time
+import tornado.concurrent
import tornado.locale
import tornado.web
import tornado.websocket
# Send the response
self.finish(html)
- def write_error(self, code, exc_info=None, **kwargs):
+ async def _execute(self, transforms, *args, **kwargs):
+ """
+ Executes this request
+ """
+ self._transforms = transforms
+
+ try:
+ # Raise error if the method is not supported
+ if self.request.method not in self.SUPPORTED_METHODS:
+ raise HTTPError(405)
+
+ # Parse arguments
+ self.path_args = [self.decode_argument(arg) for arg in args]
+ self.path_kwargs = {
+ k : self.decode_argument(v, name=k) for (k, v) in kwargs.items()
+ }
+
+ # Check the XSRF cookie
+ if not self.request.method in ("GET", "HEAD", "OPTIONS"):
+ self.check_xsrf_cookie()
+
+ # Prepare the request
+ result = self.prepare()
+ if result:
+ await result
+
+ # Tell the application we are now ready to receive the body
+ if self._prepared_future:
+ tornado.concurrent.future_set_result_unless_cancelled(
+ self._prepared_future, None
+ )
+ if self._finished:
+ return
+
+ # In streaming mode, we have to wait until the entire body has been received
+ if tornado.web._has_stream_request_body(self.__class__):
+ try:
+ await self.request._body_future
+ except tornado.iostream.StreamClosedError:
+ return
+
+ # Fetch the implementation
+ method = getattr(self, self.request.method.lower())
+
+ # Call the method
+ result = method(*self.path_args, **self.path_kwargs)
+ if result:
+ await result
+
+ # Automatically finish?
+ if self._auto_finish and not self._finished:
+ self.finish()
+
+ except Exception as e:
+ try:
+ await self._handle_request_exception(e)
+ except Exception:
+ log.error("Exception in exception handler", exc_info=True)
+
+ async def _handle_request_exception(self, e):
+ # Not really an error, just finish the request
+ if isinstance(e, tornado.web.Finish):
+ if not self._finished:
+ self.finish(*e.args)
+ return
+
+ # Fetch more information about this exception
+ exc_info = sys.exc_info()
+
+ # Log the exception
+ try:
+ self.log_exception(*exc_info)
+ except Exception:
+ log.error("Error in exception logger", exc_info=True)
+
+ # We cannot send an error if something has already been sent,
+ # so we just log the exception and are done.
+ if self._finished:
+ return
+
+ if isinstance(e, tornado.web.HTTPError):
+ await self.send_error(e.status_code, exc_info=exc_info)
+ else:
+ await self.send_error(500, exc_info=exc_info)
+
+ async def send_error(self, status_code=500, **kwargs):
+ """
+ Sends a HTTP error to the browser.
+ """
+ if self._headers_written:
+ log.error("Cannot send error response after headers written")
+ if not self._finished:
+ try:
+ self.finish()
+ except Exception:
+ log.error("Failed to flush partial response", exc_info=True)
+ return
+
+ # Clear any headers that have been set by the handler
+ self.clear()
+
+ # Fetch the reason
+ reason = kwargs.get("reason")
+
+ # Try to extract the reason from the exception
+ try:
+ type, exception, traceback = kwargs["exc_info"]
+ except KeyError:
+ pass
+ else:
+ if isinstance(exception, tornado.web.HTTPError) and exception.reason:
+ reason = exception.reason
+
+ # Set the status code
+ self.set_status(status_code, reason=reason)
+
+ # Render the error message
+ try:
+ await self.write_error(status_code, **kwargs)
+ except Exception:
+ log.error("Uncaught exception in write_error", exc_info=True)
+
+ # Make sure we are finished now to release the socket
+ if not self._finished:
+ self.finish()
+
+ async def write_error(self, code, exc_info=None, **kwargs):
try:
message = http.client.responses[code]
except KeyError:
if self.current_user.is_admin():
_traceback += traceback.format_exception(*exc_info)
- self.render("errors/error.html",
+ await self.render("errors/error.html",
code=code, message=message, traceback="".join(_traceback), **kwargs)
# Typed Arguments