def _post_data(self, context): """POST data to the the Exceptional API. If DEBUG is True then data is sent to ``EXCEPTIONAL_DEBUG_URL`` if it has been defined. If TESTING is true, error data is stored in the global ``flask.g.exceptional`` variable. :param context: The current application context. """ traceback = tbtools.get_current_traceback() error_data = json.dumps({ "application_environment": self.__get_application_data(context.app), "client": context.app.extensions["exceptional"], "request": self.__get_request_data(context.app, context.request, context.session), "exception": self.__get_exception_data(traceback) }) if context.app.testing: g.exceptional = error_data if self.url: request = Request(self.url) request.add_header("Content-Type", "application/json") if context.app.debug: data = error_data else: request.add_header("Content-Encoding", "deflate") data = compress(error_data, 1) try: urlopen(request, data) except URLError: message = "Unable to connect to {0}. See \ http://status.getexceptional.com for details. Error data:\n{1}".format(self.url, error_data) self.app.logger.warning(message, exc_info=True)
def send_exception(subject): """Send Python exception tracebacks via email to the ADMINS list. Use the same HTML styling as Flask tracebacks in debug web servers. This function must be called while the exception is happening. It picks up the raised exception with sys.exc_info(). Positional arguments: subject -- subject line of the email (to be prepended by 'Application Error: '). """ # Generate and modify html. tb = tbtools.get_current_traceback() # Get exception information. with _override_html(): html = tb.render_full().encode('utf-8', 'replace') html = html.replace('<blockquote>', '<blockquote style="margin: 1em 0 0; padding: 0;">') subject = 'Application Error: {}'.format(subject) # Apply throttle. md5 = hashlib.md5('{}{}'.format(subject, html)).hexdigest() seconds = int(current_app.config['MAIL_EXCEPTION_THROTTLE']) lock = redis.lock(EMAIL_THROTTLE.format(md5=md5), timeout=seconds) have_lock = lock.acquire(blocking=False) if not have_lock: current_app.logger.debug('Suppressing email: {}'.format(subject)) return # Send email. msg = Message(subject=subject, recipients=current_app.config['ADMINS'], html=html) mail.send(msg)
def send_exception(subject): """Send Python exception tracebacks via email to the ADMINS list. Use the same HTML styling as Flask tracebacks in debug web servers. This function must be called while the exception is happening. It picks up the raised exception with sys.exc_info(). Positional arguments: subject -- subject line of the email (to be prepended by 'Application Error: '). """ # Generate and modify html. tb = tbtools.get_current_traceback() # Get exception information. with _override_html(): html = tb.render_full().encode('utf-8', 'replace') html = html.replace('<blockquote>', '<blockquote style="margin: 1em 0 0; padding: 0;">') subject = 'Application Error: {}'.format(subject) # Apply throttle. # I should apply a throttle here, but the template uses redis, and I'm not planning on having that... # Send email. msg = Message(subject=subject, recipients=current_app.config['ADMINS'], html=html) mail.send(msg)
def json_response(f, *args, **kwargs): try: response = f(*args, **kwargs) except HTTPException as e: data = {'error': str(e), 'description': e.description} return jsonify(data), e.code except Exception as e: app.logger.error('Exception during json request: %r', e) # Werkzeug sends the response and then logs, which is fiddly from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(ignore_system_exceptions=True) app.logger.info('Traceback %s', traceback.plaintext) data = {'error': e.__class__.__name__, 'description': str(e)} return jsonify(data), 500 else: if isinstance(response, (app.response_class, BaseResponse)): return response return jsonify(response), 200
def debug_application(self, environ, start_response): app_iter = None try: app_iter = self.app(environ, start_response) for item in app_iter: yield item if hasattr(app_iter, 'close'): app_iter.close() except: if hasattr(app_iter, 'close'): app_iter.close() traceback = get_current_traceback(skip=1, show_hidden_frames=self.show_hidden_frames, ignore_system_exceptions=True) for frame in traceback.frames: self.frames[frame.id] = frame self.tracebacks[traceback.id] = traceback try: start_response('500 INTERNAL SERVER ERROR', [('Content-Type', 'text/html; charset=utf-8')]) except: environ['wsgi.errors'].write('Debugging middleware caught exception in streamed response at a point where response headers were already sent.\n') else: yield traceback.render_full(evalex=self.evalex).encode('utf-8', 'replace') traceback.log(environ['wsgi.errors'])
def send_exception(subject): """Send Python exception tracebacks via email to the ADMINS list. Use the same HTML styling as Flask tracebacks in debug web servers. This function must be called while the exception is happening. It picks up the raised exception with sys.exc_info(). Positional arguments: subject -- subject line of the email. """ # Generate and modify html. tb = tbtools.get_current_traceback() # Get exception information. with _override_html(): html = tb.render_full().encode('utf-8', 'replace') html = html.replace('<blockquote>', '<blockquote style="margin: 1em 0 0; padding: 0;">') subject = '[FRLA.mobile CMS] Application Error: {}'.format(subject) # Send email. mail.send_email( subject=subject, to=[{ 'email%s' % idx: email for idx, email in enumerate(current_app.config['ADMINS']) }], html=html)
def __call__(self, error): template_fname = self.data_browser.error_template if isinstance(error, PermissionDenied): permissions = [] for idx, need in enumerate(error.args[0].needs): permissions.append(str(need)) err_msg = _( u'this operation needs the following permissions: %(permissions)s, contact administrator to grant ' u'them!', permissions=";".join(permissions)) elif isinstance(error, ValidationError): err_msg = ",".join("%s: %s" % (k, v) for k, v in error.args[0].items()) elif isinstance(error, NotFound): err_msg = _("Sorry, object doesn't exist!") else: # we need to log the crime scene # note, this is the last line of defence, we must resolve it here! traceback = get_current_traceback(skip=1, show_hidden_frames=False, ignore_system_exceptions=True) self.data_browser.app.logger.error("%s %s" % (request.method, request.url)) self.data_browser.app.logger.error(traceback.plaintext) err_msg = _(u'Internal error "%(err)s", please contact us!', err=str(error)) return render_template(template_fname, hint_message=err_msg, error=error, back_url=request.args.get("url", "/"))
def debug_application(self, environ, start_response): app_iter = None try: app_iter = self.app(environ, start_response) for item in app_iter: yield item if hasattr(app_iter, 'close'): app_iter.close() except: if hasattr(app_iter, 'close'): app_iter.close() traceback = get_current_traceback( skip=1, show_hidden_frames=self.show_hidden_frames, ignore_system_exceptions=True) for frame in traceback.frames: self.frames[frame.id] = frame self.tracebacks[traceback.id] = traceback try: start_response('500 INTERNAL SERVER ERROR', [('Content-Type', 'text/html; charset=utf-8')]) except: environ['wsgi.errors'].write( 'Debugging middleware caught exception in streamed response at a point where response headers were already sent.\n' ) else: yield traceback.render_full(evalex=self.evalex).encode( 'utf-8', 'replace') traceback.log(environ['wsgi.errors'])
def errorlog(exception): """ We want to log exception information to file for later investigation """ traceback = get_current_traceback(ignore_system_exceptions=True, show_hidden_frames=True) log.error(traceback.plaintext) last = traceback.frames[-1] now = datetime.datetime.now().replace(microsecond=0) return render_template("error.html", now=now, name=os.path.basename(last.filename), line=last.lineno, exception=exception)
async def _debug_application(self, message, channels): """Run the application and conserve the traceback frames.""" try: await self.app(message, channels) except Exception: traceback = get_current_traceback( skip=1, show_hidden_frames=self.show_hidden_frames, ignore_system_exceptions=True) for frame in traceback.frames: self.frames[frame.id] = frame self.tracebacks[traceback.id] = traceback status = 500 headers = [ (b'Content-Type', b'text/html; charset=utf-8'), # Disable Chrome's XSS protection, the debug # output can cause false-positives. (b'X-XSS-Protection', b'0'), ] environ = utils.message_to_environ(message) is_trusted = bool(self.check_pin_trust(environ)) content = traceback.render_full(evalex=self.evalex, evalex_trusted=is_trusted, secret=self.secret).encode( 'utf-8', 'replace') await channels['reply'].send({ 'status': status, 'headers': headers, 'content': content })
async def asgi_wrapper(receive, send): try: return await application(receive, send) except Exception: traceback = get_current_traceback( skip=1, show_hidden_frames=self.show_hidden_frames, ignore_system_exceptions=True) for frame in traceback.frames: self.frames[frame.id] = frame self.tracebacks[traceback.id] = traceback environ = utils.message_to_environ(self.scope) is_trusted = sync_to_async(self.check_pin_trust)(environ) _traceback = traceback.render_full(evalex=self.evalex, evalex_trusted=is_trusted, secret=self.secret).encode( 'utf-8', 'replace') headers = [ (b'Content-Type', b'text/html; charset=utf-8'), # Disable Chrome's XSS protection, the debug # output can cause false-positives. (b'X-XSS-Protection', b'0'), ] response = http_response(self.scope, body=_traceback, status=500, headers=headers) return await response(receive, send)
def debug_application(self, environ, start_response): """Run the application and conserve the traceback frames.""" app_iter = None try: app_iter = self.app(environ, start_response) for item in app_iter: yield item if hasattr(app_iter, "close"): app_iter.close() except Exception: if hasattr(app_iter, "close"): app_iter.close() traceback = get_current_traceback( skip=1, show_hidden_frames=self.show_hidden_frames, ignore_system_exceptions=True ) for frame in traceback.frames: self.frames[frame.id] = frame self.tracebacks[traceback.id] = traceback try: start_response("500 INTERNAL SERVER ERROR", [("Content-Type", "text/html; charset=utf-8")]) except Exception: # if we end up here there has been output but an error # occurred. in that situation we can do nothing fancy any # more, better log something into the error log and fall # back gracefully. environ["wsgi.errors"].write( "Debugging middleware caught exception in streamed " "response at a point where response headers were already " "sent.\n" ) else: yield traceback.render_full(evalex=self.evalex).encode("utf-8", "replace") traceback.log(environ["wsgi.errors"])
def get_current_traceback(self): "Get the current Python traceback, keeping stack frames in debug app." traceback = get_current_traceback() for frame in traceback.frames: self.debug_app.frames[frame.id] = frame self.debug_app.tracebacks[traceback.id] = traceback return traceback
def get_current_traceback(self): "Get the current Python traceback, keeping stack frames in debug app." # https://gist.github.com/rduplain/4983839 traceback = get_current_traceback() for frame in traceback.frames: self.debug_app.frames[frame.id] = frame self.debug_app.tracebacks[traceback.id] = traceback return traceback
def wrapper(request): try: response = func(request) except Exception as e: tb = get_current_traceback() return responses.InternalServerError(render_function(tb), headers={"Content-type": content_type}) return response
def get_current_traceback(): "Get the current traceback in debug mode, using werkzeug debug tools." # Lazy import statement, as debugger is only used in development. from werkzeug.debug.tbtools import get_current_traceback # Experiment with skip argument, to skip stack frames in traceback. traceback = get_current_traceback(skip=2, show_hidden_frames=False, ignore_system_exceptions=True) return traceback
def exception_handler(e): tb = get_current_traceback() last_frame = tb.frames[-1] last_frame_args = inspect.getargs(last_frame.code) return render_template('show_error.html', tb=tb, last_frame=last_frame, last_frame_args=last_frame_args), 500
def render_exception(self): traceback = get_current_traceback() for frame in traceback.frames: self.debugger.frames[frame.id] = frame self.debugger.tracebacks[traceback.id] = traceback return traceback.render_full(evalex=True, secret=self.debugger.secret)
def nfmp(): try: content = request.get_json() return jsonify(run_nfmp(content)) except Exception as e: track = get_current_traceback(skip=1, show_hidden_frames=True, ignore_system_exceptions=False) track.log() abort(500)
def exception_handler(e): tb = get_current_traceback() last_frame = next(frame for frame in reversed(tb.frames) if not frame.is_library) last_frame_args = inspect.getargs(last_frame.code) return render_template('show_error.html', tb=tb, last_frame=last_frame, last_frame_args=last_frame_args), 500
def wrapper(request, *args, **kwargs): try: response = func(request, *args, **kwargs) except Exception: tb = get_current_traceback() return responses.InternalServerError( render_function(tb), headers={"Content-type": content_type}) return response
def exception_handler(e): tb = get_current_traceback() return render_template('show_error.html', tb=tb), 500 exc_type, exc_value, tb = sys.exc_info() if exc_value is e: reraise(exc_type, exc_value, tb) else: raise e
def _wrap_errors(_): """Install traceback handling for callbacks""" self._traceback = sys.exc_info()[2] # Compute number of stack frames to skip to get down to callback tb_werkzeug = get_current_traceback() skip = 0 if dev_tools_prune_errors: for i, line in enumerate(tb_werkzeug.plaintext.splitlines()): if "%% callback invoked %%" in line: skip = int((i + 1) / 2) break # Customized formatargvalues function so we can place function parameters # on separate lines original_formatargvalues = inspect.formatargvalues inspect.formatargvalues = _custom_formatargvalues try: # Use IPython traceback formatting to build colored ANSI traceback # string ostream = io.StringIO() ipytb = FormattedTB( tb_offset=skip, mode="Verbose", color_scheme="Linux", include_vars=True, ostream=ostream ) ipytb() finally: # Restore formatargvalues inspect.formatargvalues = original_formatargvalues # Print colored ANSI representation if requested ansi_stacktrace = ostream.getvalue() if inline_exceptions: print(ansi_stacktrace) # Use ansi2html to convert the colored ANSI string to HTML conv = Ansi2HTMLConverter(scheme="ansi2html", dark_bg=False) html_str = conv.convert(ansi_stacktrace) # Set width to fit 75-character wide stack trace and font to a size the # won't require a horizontal scroll bar html_str = html_str.replace( '<html>', '<html style="width: 75ch; font-size: 0.86em">' ) # Remove explicit background color so Dash dev-tools can set background # color html_str = re.sub("background-color:[^;]+;", "", html_str) return html_str, 500
def handle_request(self, req): with self.request_context(req): try: response = self.full_dispatch_request() except Exception, e: self.log_exception(e) try: response = self.make_response(self.handle_exception(e)) except: tb = tbtools.get_current_traceback(skip=1) response = Response(tb.render_summary(), headers={'Content-Type' : 'text/html'})
def handle_request(self, req): with self.request_context(req): try: response = self.full_dispatch_request() except Exception, e: self.log_exception(e) try: response = self.make_response(self.handle_exception(e)) except: tb = tbtools.get_current_traceback(skip=1) response = Response(tb.render_summary(), headers={'Content-Type': 'text/html'})
def error(error): if isinstance(error, SQLAlchemyError): from lite_mms.database import db db.session.rollback() from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(skip=1, show_hidden_frames=False, ignore_system_exceptions=True) app.logger.error("%s %s" % (request.method, request.url)) app.logger.error(traceback.plaintext) sender_email(traceback) return redirect(url_for("error", errors=u"%s %s时,系统异常" % (request.method, request.url), detail=traceback.render_summary(), url=request.args.get("url", "/")))
def error(error): if isinstance(error, SQLAlchemyError): from cloud_dashing.database import db db.session.rollback() from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(skip=1, show_hidden_frames=False, ignore_system_exceptions=True) app.logger.error("%s %s" % (request.method, request.url)) app.logger.error(traceback.plaintext) sender_email(traceback) return render_template("error.html", error=_("Failed to %(method)s %(url)s", method=request.method, url=request.url), detail=traceback.render_summary(), back_url=request.args.get("__back_url__", "/"))
def debug_application(self, environ, start_response): """Run the application and conserve the traceback frames.""" app_iter = None try: app_iter = self.app(environ, start_response) for item in app_iter: yield item if hasattr(app_iter, "close"): app_iter.close() except Exception: if hasattr(app_iter, "close"): app_iter.close() traceback = get_current_traceback( skip=1, show_hidden_frames=self.show_hidden_frames, ignore_system_exceptions=True, ) for frame in traceback.frames: self.frames[frame.id] = frame self.tracebacks[traceback.id] = traceback try: start_response( "500 INTERNAL SERVER ERROR", [ ("Content-Type", "text/html; charset=utf-8"), # Disable Chrome's XSS protection, the debug # output can cause false-positives. ("X-XSS-Protection", "0"), ], ) except Exception: # if we end up here there has been output but an error # occurred. in that situation we can do nothing fancy any # more, better log something into the error log and fall # back gracefully. environ["wsgi.errors"].write( "Debugging middleware caught exception in streamed " "response at a point where response headers were already " "sent.\n" ) else: is_trusted = bool(self.check_pin_trust(environ)) yield traceback.render_full( evalex=self.evalex, evalex_trusted=is_trusted, secret=self.secret ).encode("utf-8", "replace") traceback.log(environ["wsgi.errors"])
def error(error): if isinstance(error, SQLAlchemyError): from litefac.database import db db.session.rollback() from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(skip=1, show_hidden_frames=False, ignore_system_exceptions=True) app.logger.error("%s %s" % (request.method, request.url)) app.logger.error(traceback.plaintext) sender_email(traceback) return render_template("error.html", msg=u"%s %s时,系统异常" % (request.method, request.url), detail=traceback.render_summary(), back_url=request.args.get("back_url", "/"), nav_bar=nav_bar, titlename=u"错误"), 403
def error(error): if isinstance(error, SQLAlchemyError): db.session.rollback() from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(skip=1, show_hidden_frames=False, ignore_system_exceptions=True) app.logger.error("%s %s" % (request.method, request.url)) app.logger.error(traceback.plaintext) email_exception(traceback) return render_template('error.html', title=_(u"failed request: %(method)s %(url)s", method=request.method, url=request.url), text=traceback.render_summary(), backref=request.args.get('backref', '/'))
def debug_application(self, environ, start_response): """Run the application and conserve the traceback frames.""" app_iter = None try: app_iter = self.app(environ, start_response) for item in app_iter: yield item if hasattr(app_iter, 'close'): app_iter.close() except Exception: if hasattr(app_iter, 'close'): app_iter.close() traceback = get_current_traceback( skip=1, show_hidden_frames=self.show_hidden_frames, ignore_system_exceptions=True) for frame in traceback.frames: self.frames[frame.id] = frame self.tracebacks[traceback.id] = traceback try: start_response( '500 INTERNAL SERVER ERROR', [ ('Content-Type', 'text/html; charset=utf-8'), # Disable Chrome's XSS protection, the debug # output can cause false-positives. ('X-XSS-Protection', '0'), ]) except Exception: # if we end up here there has been output but an error # occurred. in that situation we can do nothing fancy any # more, better log something into the error log and fall # back gracefully. environ['wsgi.errors'].write( 'Debugging middleware caught exception in streamed ' 'response at a point where response headers were already ' 'sent.\n') else: yield traceback.render_full(evalex=self.evalex, lodgeit_url=self.lodgeit_url, secret=self.secret) \ .encode('utf-8', 'replace') traceback.log(environ['wsgi.errors'])
def error(error): if isinstance(error, SQLAlchemyError): from lite_mms.database import db db.session.rollback() from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(skip=1, show_hidden_frames=False, ignore_system_exceptions=True) app.logger.error("%s %s" % (request.method, request.url)) app.logger.error(traceback.plaintext) sender_email(traceback) return redirect( url_for("error", errors=u"%s %s时,系统异常" % (request.method, request.url), detail=traceback.render_summary(), url=request.args.get("url", "/")))
def debug_application(self, environ, start_response): """Run the application and conserve the traceback frames.""" app_iter = None try: app_iter = self.app(environ, start_response) for item in app_iter: yield item if hasattr(app_iter, 'close'): app_iter.close() except Exception: if hasattr(app_iter, 'close'): app_iter.close() traceback = get_current_traceback( skip=1, show_hidden_frames=self.show_hidden_frames, ignore_system_exceptions=True) for frame in traceback.frames: self.frames[frame.id] = frame self.tracebacks[traceback.id] = traceback try: start_response('500 INTERNAL SERVER ERROR', [ ('Content-Type', 'text/html; charset=utf-8'), # Disable Chrome's XSS protection, the debug # output can cause false-positives. ('X-XSS-Protection', '0'), ]) except Exception: # if we end up here there has been output but an error # occurred. in that situation we can do nothing fancy any # more, better log something into the error log and fall # back gracefully. environ['wsgi.errors'].write( 'Debugging middleware caught exception in streamed ' 'response at a point where response headers were already ' 'sent.\n') else: is_trusted = bool(self.check_pin_trust(environ)) yield traceback.render_full(evalex=self.evalex, evalex_trusted=is_trusted, secret=self.secret) \ .encode('utf-8', 'replace') traceback.log(environ['wsgi.errors'])
def debug_application(self, environ, start_response): """Run the application and conserve the traceback frames.""" app_iter = None try: app_iter = self.app(environ, start_response) for item in app_iter: yield item if hasattr(app_iter, 'close'): app_iter.close() except Exception: if hasattr(app_iter, 'close'): app_iter.close() traceback = get_current_traceback(skip=1, show_hidden_frames= self.show_hidden_frames, ignore_system_exceptions=True) for frame in traceback.frames: self.frames[frame.id] = frame self.tracebacks[traceback.id] = traceback try: start_response('500 INTERNAL SERVER ERROR', [ ('Content-Type', 'text/html; charset=utf-8') ]) except Exception: # if we end up here there has been output but an error # occurred. in that situation we can do nothing fancy any # more, better log something into the error log and fall # back gracefully. environ['wsgi.errors'].write( 'Debugging middleware caught exception in streamed ' 'response at a point where response headers were already ' 'sent.\n') else: yield traceback.render_full(evalex=self.evalex, lodgeit_url=self.lodgeit_url, secret=self.secret, pid=self.multiprocess_support and getpid() or '') \ .encode('utf-8', 'replace') traceback.log(environ['wsgi.errors'])
def wrapper(request, *args, **kwargs): try: return func(request, *args, **kwargs) except api_exceptions.NotFound as ex: return responses.NotFound(**_render_error(ex)) except api_exceptions.Forbidden as ex: return responses.Forbidden(**_render_error(ex)) except api_exceptions.BadRequest as ex: return responses.BadRequest(**_render_error(ex)) except Exception as ex: if settings.DEBUG == False: return responses.InternalServerError(**_render_error(ex, "Internal error: {}".format(str(ex)))) else: from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback() return responses.InternalServerError( traceback.plaintext, headers={"Content-type": "text/plain"} )
def wrapper(request, *args, **kwargs): try: return func(request, *args, **kwargs) except api_exceptions.NotFound as ex: return responses.NotFound(**_render_error(ex)) except api_exceptions.Forbidden as ex: return responses.Forbidden(**_render_error(ex)) except api_exceptions.BadRequest as ex: return responses.BadRequest(**_render_error(ex)) except Exception as ex: if settings.DEBUG == False: return responses.InternalServerError( **_render_error(ex, "Internal error: {}".format(str(ex)))) else: from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback() return responses.InternalServerError( traceback.plaintext, headers={"Content-type": "text/plain"})
def showsyntaxerror(self, filename=None): from werkzeug.debug.tbtools import get_current_traceback tb = get_current_traceback(skip=4) sys.stdout._write(tb.render_summary())
def run_wsgi(self): app = self.server.app environ = self.make_environ() headers_set = [] headers_sent = [] def write(data): if not headers_sent: status, response_headers = headers_sent[:] = headers_set code, msg = status.split(None, 1) self.send_response(int(code), msg) header_keys = set() for key, value in response_headers: self.send_header(key, value) key = key.lower() header_keys.add(key) if 'content-length' not in header_keys: self.close_connection = True self.send_header('Connection', 'close') if 'server' not in header_keys: self.send_header('Server', self.version_string()) if 'date' not in header_keys: self.send_header('Date', self.date_time_string()) self.end_headers() self.wfile.write(data) self.wfile.flush() def start_response(status, response_headers, exc_info=None): if exc_info: try: if headers_sent: raise exc_info[0], exc_info[1], exc_info[2] finally: exc_info = None elif headers_set: raise AssertionError('Headers already set') headers_set[:] = [status, response_headers] return write def execute(app): application_iter = app(environ, start_response) try: for data in application_iter: write(data) if not headers_sent: write('') finally: if hasattr(application_iter, 'close'): application_iter.close() application_iter = None try: execute(app) except (socket.error, socket.timeout) as e: self.connection_dropped(e, environ) except: if self.server.passthrough_errors: raise from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(ignore_system_exceptions=True) try: if not headers_sent: del headers_set[:] execute(InternalServerError()) except: pass self.server.log('error', 'Error on request:\n%s', traceback.plaintext)
def run_wsgi(self): # XXX: Copy paste of _WSGIRequestHandler.run_wsgi # cause there is no other way to use metrics on error if self.headers.get('Expect', '').lower().strip() == '100-continue': self.wfile.write(b'HTTP/1.1 100 Continue\r\n\r\n') self.environ = environ = self.make_environ() headers_set = [] headers_sent = [] def write(data): assert headers_set, 'write() before start_response' if not headers_sent: status, response_headers = headers_sent[:] = headers_set try: code, msg = status.split(None, 1) except ValueError: code, msg = status, "" self.send_response(int(code), msg) header_keys = set() for key, value in response_headers: self.send_header(key, value) key = key.lower() header_keys.add(key) if 'content-length' not in header_keys: self.close_connection = True self.send_header('Connection', 'close') if 'server' not in header_keys: self.send_header('Server', self.version_string()) if 'date' not in header_keys: self.send_header('Date', self.date_time_string()) self.end_headers() assert isinstance(data, bytes), 'applications must write bytes' self.wfile.write(data) self.wfile.flush() def start_response(status, response_headers, exc_info=None): if exc_info: try: if headers_sent: reraise(*exc_info) finally: exc_info = None elif headers_set: raise AssertionError('Headers already set') headers_set[:] = [status, response_headers] return write def execute(app): application_iter = app(environ, start_response) try: for data in application_iter: write(data) if not headers_sent: write(b'') finally: if hasattr(application_iter, 'close'): application_iter.close() application_iter = None try: execute(self.server.app) except (socket.error, socket.timeout) as e: self.connection_dropped(e, environ) except Exception: # XXX: all that copy-paste for the sake of this line wsgi.exception.enter() if self.server.passthrough_errors: raise from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(ignore_system_exceptions=True) try: # if we haven't yet sent the headers but they are set # we roll back to be able to set them again. if not headers_sent: del headers_set[:] execute(InternalServerError()) except Exception: print("EXCEPTION IN EXCEPTION") pass self.server.log('error', 'Error on request:\n%s', traceback.plaintext)
if not headers_sent: write('') finally: if hasattr(application_iter, 'close'): application_iter.close() application_iter = None try: execute(app) except (socket.error, socket.timeout), e: self.connection_dropped(e, environ) except: if self.server.passthrough_errors: raise from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(ignore_system_exceptions=True) try: # if we haven't yet sent the headers but they are set # we roll back to be able to set them again. if not headers_sent: del headers_set[:] execute(InternalServerError()) except: pass self.server.log('error', 'Error on request:\n%s', traceback.plaintext) def handle(self): """Handles a request ignoring dropped connections.""" try: return BaseHTTPRequestHandler.handle(self)
def internal_error(exception): app.logger.exception(exception) tb = tbtools.get_current_traceback() print "traceback", tb return flask.render_template('500.html', exception=exception, traceback=tb.plaintext)
def _emit(self, record, **kwargs): data = { 'params': record.args, 'created': record.created, } try: data['message'] = force_text(record.msg) except UnicodeDecodeError: # Handle binary strings where it should be unicode... data['message'] = repr(record.msg)[1:-1] try: data['formatted'] = force_text(record.message) except UnicodeDecodeError: # Handle binary strings where it should be unicode... data['formatted'] = repr(record.message)[1:-1] if record.exc_info and all(record.exc_info): # Record all details we can find from the current exception. tb = get_current_traceback(skip=1) exc = escape(tb.exception) serialized_frames = [] for frame in tb.frames: serialized_frame = { 'id': frame.id, 'filename': escape(frame.filename), 'lineno': frame.lineno, 'function_name': escape(frame.function_name), 'current_line': escape(frame.current_line.strip()), 'sourcelines': frame.sourcelines, 'lines': [] } for line in frame.get_annotated_lines(): serialized_frame['lines'].append({ 'classes': line.classes, 'lineno': line.lineno, 'code': escape(line.code) }) serialized_frames.append(serialized_frame) data['traceback'] = { 'title': exc, 'exception': exc, 'exception_type': escape(tb.exception_type), 'frames': serialized_frames, 'plaintext': tb.plaintext, 'traceback_id': tb.id, } data['level'] = record.levelno data['logger'] = record.name if hasattr(record, 'tags'): data['tags'] = record.tags if hasattr(record, 'extra'): data['extra'] = record.extra endpoint = self.host + reverse('api-v1:message') headers = {'content-type': 'application/json'} # TODO: error handling. requests.post(endpoint, data=json.dumps(data), headers=headers)
def run_wsgi(self): app = self.server.app environ = self.make_environ() headers_set = [] headers_sent = [] def write(data): if not headers_sent: status, response_headers = headers_sent[:] = headers_set code, msg = status.split(None, 1) self.send_response(int(code), msg) header_keys = set() for key, value in response_headers: self.send_header(key, value) key = key.lower() header_keys.add(key) if 'content-length' not in header_keys: self.close_connection = True self.send_header('Connection', 'close') if 'server' not in header_keys: self.send_header('Server', self.version_string()) if 'date' not in header_keys: self.send_header('Date', self.date_time_string()) self.end_headers() self.wfile.write(data) self.wfile.flush() def start_response(status, response_headers, exc_info = None): if exc_info: try: if headers_sent: raise exc_info[0], exc_info[1], exc_info[2] finally: exc_info = None elif headers_set: raise AssertionError('Headers already set') headers_set[:] = [status, response_headers] return write def execute(app): application_iter = app(environ, start_response) try: for data in application_iter: write(data) if not headers_sent: write('') finally: if hasattr(application_iter, 'close'): application_iter.close() application_iter = None try: execute(app) except (socket.error, socket.timeout) as e: self.connection_dropped(e, environ) except: if self.server.passthrough_errors: raise from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(ignore_system_exceptions=True) try: if not headers_sent: del headers_set[:] execute(InternalServerError()) except: pass self.server.log('error', 'Error on request:\n%s', traceback.plaintext)
if not headers_sent: write('') finally: if hasattr(application_iter, 'close'): application_iter.close() application_iter = None try: execute(app) except (socket.error, socket.timeout), e: self.connection_dropped(e, environ) except: if self.server.passthrough_errors: raise from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(ignore_system_exceptions=True) try: # if we haven't yet sent the headers but they are set # we roll back to be able to set them again. if not headers_sent: del headers_set[:] execute(InternalServerError()) except: pass self.server.log('error', 'Error on request:\n%s', traceback.plaintext) def connection_dropped(self, error, environ): """Called if the connection was closed by the client. By default nothing happens. """
def _post_data(self, context=None, traceback=None): """POST data to the the Exceptional API. If DEBUG is True then data is sent to ``EXCEPTIONAL_DEBUG_URL`` if it has been defined. If TESTING is true, error data is stored in the global ``flask.g.exceptional`` variable. :param context: Default ``None``. The current application context. :param traceback: Default ``None``. The exception stack trace. """ app = context.app if context else stack.top.app application_data = self.__get_application_data(app) client_data = { "name": "flask-exceptional", "version": self.__version__, "protocol_version": self.__protocol_version } if context: request_data = self.__get_request_data(app, context.request, context.session) context_data = getattr(context, "exceptional_context", None) else: request_data = None context_data = None traceback = traceback or tbtools.get_current_traceback() exception_data = self.__get_exception_data(traceback) encode_basestring = json.encoder.encode_basestring def _encode_basestring(value): if isinstance(value, str) and \ json.encoder.HAS_UTF8.search(value) is not None: value = value.decode("utf-8", "replace") # ensure the decode succeeds. replace = lambda match: json.encoder.ESCAPE_DCT[match.group(0)] return u'"%s"' % json.encoder.ESCAPE.sub(replace, value) try: json.encoder.encode_basestring = _encode_basestring error_data = json.dumps({ "application_environment": application_data, "client": client_data, "request": request_data, "exception": exception_data, "context": context_data }, ensure_ascii=False).encode("utf-8") finally: json.encoder.encode_basestring = encode_basestring if app.testing: g.exceptional = error_data if self.url: request = Request(self.url) request.add_header("Content-Type", "application/json") if app.debug: data = error_data else: request.add_header("Content-Encoding", "deflate") data = compress(error_data, 1) try: try: urlopen(request, data) except HTTPError, e: if e.code >= 400: raise except URLError: message = "Unable to connect to %s. See http://status.exceptional.io for details. Error data:\n%s" # NOQA app.logger.warning(message, self.url, error_data, exc_info=True) except BadStatusLine: pass
def run_wsgi(self): environ = self.make_environ() headers_set = [] headers_sent = [] def write(data): assert headers_set, 'write() before start_response' if not headers_sent: status, response_headers = headers_sent[:] = headers_set try: code, msg = status.split(None, 1) except ValueError: code, msg = status, "" self.send_response(int(code), msg) header_keys = set() for key, value in response_headers: self.send_header(key, value) key = key.lower() header_keys.add(key) if 'content-length' not in header_keys: self.close_connection = True self.send_header('Connection', 'close') if 'server' not in header_keys: self.send_header('Server', self.version_string()) if 'date' not in header_keys: self.send_header('Date', self.date_time_string()) self.end_headers() assert type(data) is bytes, 'applications must write bytes' self.wfile.write(data) self.wfile.flush() def start_response(status, response_headers, exc_info=None): if exc_info: try: if headers_sent: reraise(*exc_info) finally: exc_info = None elif headers_set: raise AssertionError('Headers already set') headers_set[:] = [status, response_headers] return write def app_proxy(environ, start_response): # We reject an invalid content length here because it can cause # problems with how WSGI apps respond to values in it. content_length = environ['CONTENT_LENGTH'] if content_length and not content_length.isdigit(): resp = BadRequest() else: resp = self.server.app return resp(environ, start_response) def execute(app): application_iter = app(environ, start_response) try: for data in application_iter: write(data) if not headers_sent: write(b'') finally: if hasattr(application_iter, 'close'): application_iter.close() application_iter = None try: execute(app_proxy) except (socket.error, socket.timeout) as e: self.connection_dropped(e, environ) except Exception: if self.server.passthrough_errors: raise from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(ignore_system_exceptions=True) try: # if we haven't yet sent the headers but they are set # we roll back to be able to set them again. if not headers_sent: del headers_set[:] execute(InternalServerError()) except Exception: pass self.server.log('error', 'Error on request:\n%s', traceback.plaintext)
def run_wsgi(self): if self.headers.get("Expect", "").lower().strip() == "100-continue": self.wfile.write(b"HTTP/1.1 100 Continue\r\n\r\n") environ = self.make_environ() headers_set = [] headers_sent = [] def write(data): assert headers_set, "write() before start_response" if not headers_sent: status, response_headers = headers_sent[:] = headers_set try: code, msg = status.split(None, 1) except ValueError: code, msg = status, "" self.send_response(int(code), msg) header_keys = set() for key, value in response_headers: self.send_header(key, value) key = key.lower() header_keys.add(key) if "content-length" not in header_keys: self.close_connection = True self.send_header("Connection", "close") if "server" not in header_keys: self.send_header("Server", self.version_string()) if "date" not in header_keys: self.send_header("Date", self.date_time_string()) self.end_headers() assert type(data) is bytes, "applications must write bytes" self.wfile.write(data) self.wfile.flush() def start_response(status, response_headers, exc_info=None): if exc_info: try: if headers_sent: reraise(*exc_info) finally: exc_info = None elif headers_set: raise AssertionError("Headers already set") headers_set[:] = [status, response_headers] return write def execute(app): application_iter = app(environ, start_response) try: for data in application_iter: write(data) if not headers_sent: write(b"") finally: if hasattr(application_iter, "close"): application_iter.close() application_iter = None try: execute(self.server.app) except (socket.error, socket.timeout) as e: self.connection_dropped(e, environ) except Exception: if self.server.passthrough_errors: raise from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(ignore_system_exceptions=True) try: # if we haven't yet sent the headers but they are set # we roll back to be able to set them again. if not headers_sent: del headers_set[:] execute(InternalServerError()) except Exception: pass self.server.log("error", "Error on request:\n%s", traceback.plaintext)
def _store_traceback(self): traceback = get_current_traceback(skip=1, show_hidden_frames=False, ignore_system_exceptions=True) self.tracebacks[traceback.id] = traceback return "/debug/{}".format(traceback.id)
def showtraceback(self): from werkzeug.debug.tbtools import get_current_traceback tb = get_current_traceback(skip=1) sys.stdout._write(tb.render_summary())
def run_wsgi(self): if self.headers.get("Expect", "").lower().strip() == "100-continue": self.wfile.write(b"HTTP/1.1 100 Continue\r\n\r\n") self.environ = environ = self.make_environ() headers_set = [] headers_sent = [] def write(data): assert headers_set, "write() before start_response" if not headers_sent: status, response_headers = headers_sent[:] = headers_set try: code, msg = status.split(None, 1) except ValueError: code, msg = status, "" code = int(code) self.log_request(code, data.__len__()) self.send_response(code, msg) header_keys = set() for key, value in response_headers: self.send_header(key, value) key = key.lower() header_keys.add(key) if not ( "content-length" in header_keys or environ["REQUEST_METHOD"] == "HEAD" or code < 200 or code in (204, 304) ): self.close_connection = True self.send_header("Connection", "close") if "server" not in header_keys: self.send_header("Server", self.version_string()) if "date" not in header_keys: self.send_header("Date", self.date_time_string()) self.end_headers() assert isinstance(data, bytes), "applications must write bytes" if data: # Only write data if there is any to avoid Python 3.5 SSL bug self.wfile.write(data) self.wfile.flush() def start_response(status, response_headers, exc_info=None): if exc_info: try: if headers_sent: reraise(*exc_info) finally: exc_info = None elif headers_set: raise AssertionError("Headers already set") headers_set[:] = [status, response_headers] return write def execute(app): application_iter = app(environ, start_response) try: for data in application_iter: write(data) if not headers_sent: write(b"") finally: if hasattr(application_iter, "close"): application_iter.close() try: execute(self.server.app) except (ConnectionError, socket.timeout) as e: self.connection_dropped(e, environ) except Exception: if self.server.passthrough_errors: raise from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(ignore_system_exceptions=True) try: # if we haven't yet sent the headers but they are set # we roll back to be able to set them again. if not headers_sent: del headers_set[:] execute(InternalServerError()) except Exception: pass self.server.log("error", "Error on request:\n%s", traceback.plaintext)
def run_wsgi(self): if self.headers.get('Expect', '').lower().strip() == '100-continue': self.wfile.write(b'HTTP/1.1 100 Continue\r\n\r\n') self.environ = environ = self.make_environ() headers_set = [] headers_sent = [] def write(data): assert headers_set, 'write() before start_response' if not headers_sent: status, response_headers = headers_sent[:] = headers_set try: code, msg = status.split(None, 1) except ValueError: code, msg = status, "" self.send_response(int(code), msg) header_keys = set() for key, value in response_headers: self.send_header(key, value) key = key.lower() header_keys.add(key) if 'content-length' not in header_keys: self.close_connection = True self.send_header('Connection', 'close') if 'server' not in header_keys: self.send_header('Server', self.version_string()) if 'date' not in header_keys: self.send_header('Date', self.date_time_string()) self.end_headers() assert isinstance(data, bytes), 'applications must write bytes' self.wfile.write(data) self.wfile.flush() def start_response(status, response_headers, exc_info=None): if exc_info: try: if headers_sent: reraise(*exc_info) finally: exc_info = None elif headers_set: raise AssertionError('Headers already set') headers_set[:] = [status, response_headers] return write def execute(app): application_iter = app(environ, start_response) try: for data in application_iter: write(data) if not headers_sent: write(b'') finally: if hasattr(application_iter, 'close'): application_iter.close() application_iter = None try: execute(self.server.app) except (socket.error, socket.timeout) as e: self.connection_dropped(e, environ) except Exception: if self.server.passthrough_errors: raise from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(ignore_system_exceptions=True) try: # if we haven't yet sent the headers but they are set # we roll back to be able to set them again. if not headers_sent: del headers_set[:] execute(InternalServerError()) except Exception: pass self.server.log('error', 'Error on request:\n%s', traceback.plaintext)
class WSGIRequestHandler(BaseHTTPRequestHandler, object): """A request handler that implements WSGI dispatching.""" @property def server_version(self): return 'Werkzeug/' + werkzeug.__version__ def make_environ(self): request_url = _safe_urlsplit(self.path) def shutdown_server(): self.server.shutdown_signal = True url_scheme = self.server.ssl_context is None and 'http' or 'https' environ = { 'wsgi.version': (1, 0), 'wsgi.url_scheme': url_scheme, 'wsgi.input': self.rfile, 'wsgi.errors': sys.stderr, 'wsgi.multithread': self.server.multithread, 'wsgi.multiprocess': self.server.multiprocess, 'wsgi.run_once': False, 'werkzeug.server.shutdown': shutdown_server, 'SERVER_SOFTWARE': self.server_version, 'REQUEST_METHOD': self.command, 'SCRIPT_NAME': '', 'PATH_INFO': unquote(request_url.path), 'QUERY_STRING': request_url.query, 'CONTENT_TYPE': self.headers.get('Content-Type', ''), 'CONTENT_LENGTH': self.headers.get('Content-Length', ''), 'REMOTE_ADDR': self.client_address[0], 'REMOTE_PORT': self.client_address[1], 'SERVER_NAME': self.server.server_address[0], 'SERVER_PORT': str(self.server.server_address[1]), 'SERVER_PROTOCOL': self.request_version } for key, value in self.headers.items(): key = 'HTTP_' + key.upper().replace('-', '_') if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'): environ[key] = value if request_url.netloc: environ['HTTP_HOST'] = request_url.netloc return environ def run_wsgi(self): app = self.server.app environ = self.make_environ() headers_set = [] headers_sent = [] def write(data): assert headers_set, 'write() before start_response' if not headers_sent: status, response_headers = headers_sent[:] = headers_set code, msg = status.split(None, 1) self.send_response(int(code), msg) header_keys = set() for key, value in response_headers: self.send_header(key, value) key = key.lower() header_keys.add(key) if 'content-length' not in header_keys: self.close_connection = True self.send_header('Connection', 'close') if 'server' not in header_keys: self.send_header('Server', self.version_string()) if 'date' not in header_keys: self.send_header('Date', self.date_time_string()) self.end_headers() assert type(data) is str, 'applications must write bytes' self.wfile.write(data) self.wfile.flush() def start_response(status, response_headers, exc_info=None): if exc_info: try: if headers_sent: raise exc_info[0], exc_info[1], exc_info[2] finally: exc_info = None elif headers_set: raise AssertionError('Headers already set') headers_set[:] = [status, response_headers] return write def execute(app): application_iter = app(environ, start_response) try: for data in application_iter: write(data) # make sure the headers are sent if not headers_sent: write('') finally: if hasattr(application_iter, 'close'): application_iter.close() application_iter = None try: execute(app) except (socket.error, socket.timeout), e: self.connection_dropped(e, environ) except Exception: if self.server.passthrough_errors: raise from werkzeug.debug.tbtools import get_current_traceback traceback = get_current_traceback(ignore_system_exceptions=True) try: # if we haven't yet sent the headers but they are set # we roll back to be able to set them again. if not headers_sent: del headers_set[:] execute(InternalServerError()) except Exception: pass self.server.log('error', 'Error on request:\n%s', traceback.plaintext)
def _post_data(self, context, traceback=None): """POST data to the the Exceptional API. If DEBUG is True then data is sent to ``EXCEPTIONAL_DEBUG_URL`` if it has been defined. If TESTING is true, error data is stored in the global ``flask.g.exceptional`` variable. :param context: The current application or application context. :param traceback: Default ``None``. The exception stack trace. """ if context: if isinstance(context, Flask): app = context context = None else: app = context.app else: app = stack.top.app application_data = self.__get_application_data(app) client_data = { "name": "flask-exceptional", "version": self.__version__, "protocol_version": self.__protocol_version } if context: request_data = self.__get_request_data(app, context.request, context.session) context_data = getattr(context, "exceptional_context", None) else: request_data = None context_data = None traceback = traceback or tbtools.get_current_traceback() exception_data = self.__get_exception_data(traceback) encode_basestring = json.encoder.encode_basestring def _encode_basestring(value): if isinstance(value, str) and \ json.encoder.HAS_UTF8.search(value) is not None: value = value.decode("utf-8", "replace") # ensure the decode succeeds. replace = lambda match: json.encoder.ESCAPE_DCT[match.group(0)] return u'"%s"' % json.encoder.ESCAPE.sub(replace, value) try: json.encoder.encode_basestring = _encode_basestring ret_val = json.dumps( { "application_environment": application_data, "client": client_data, "request": request_data, "exception": exception_data, "context": context_data }, ensure_ascii=False).encode("utf-8") finally: json.encoder.encode_basestring = encode_basestring if context and app.testing: g.exceptional = ret_val if self.url: request = Request(self.url) request.add_header("Content-Type", "application/json") if app.debug: data = ret_val else: request.add_header("Content-Encoding", "deflate") data = compress(ret_val, 1) try: try: urlopen(request, data) except HTTPError, e: if e.code >= 400: raise except URLError: message = "Unable to connect to %s. See http://status.exceptional.io for details. Error data:\n%s" # NOQA app.logger.warning(message, self.url, ret_val, exc_info=True) except BadStatusLine: pass return ret_val