def __call__(self, environ, start_response): """ This is straight copied from the original ErrorMiddleware code. Unfortunately they didnt separate out the actual exception handling into a function, so I must override... basically just adds the handle_async_exception() call """ # We want to be careful about not sending headers twice, # and the content type that the app has committed to (if there # is an exception in the iterator body of the response) if environ.get('paste.throw_errors'): return self.application(environ, start_response) environ['paste.throw_errors'] = True try: __traceback_supplement__ = errormiddleware.Supplement, self, environ sr_checker = errormiddleware.ResponseStartChecker(start_response) app_iter = self.application(environ, sr_checker) return self.make_catching_iter(app_iter, environ, sr_checker) except: exc_info = sys.exc_info() try: count = get_debug_count(environ) base_path = Request(environ).application_url + '/_debug/' exc_data = collector.collect_exception(*exc_info) exc_data.view_url = base_path + str(count) if self.reporters: for reporter in self.reporters: reporter.report(exc_data) #is_async is set by the @ajax decorator if environ.get('is_async', None): start_response('500 Internal Server Error', [('content-type', 'application/json; charset=utf8')], exc_info) response = handle_async_exception(exc_info, environ) else: start_response('500 Internal Server Error', [('content-type', 'text/html; charset=utf8')], exc_info) # @@: it would be nice to deal with bad content types here response = self.exception_handler(exc_info, environ) if isinstance(response, unicode): response = response.encode('utf8') return [response] finally: # clean up locals... exc_info = None
def respond(self, environ, start_response): """ This is straight copied from the original ErrorMiddleware code. Unfortunately they didnt separate out the actual exception handling into a function, so I must override... basically just adds the handle_async_exception() call """ req = Request(environ) if req.environ.get('paste.throw_errors'): return self.application(environ, start_response) base_path = req.application_url + '/_debug' req.environ['paste.throw_errors'] = True started = [] def detect_start_response(status, headers, exc_info=None): try: return start_response(status, headers, exc_info) except: raise else: started.append(True) try: __traceback_supplement__ = errormiddleware.Supplement, self, environ app_iter = self.application(environ, detect_start_response) # Don't create a list from a paste.fileapp object if isinstance(app_iter, fileapp._FileIter): return app_iter try: return_iter = list(app_iter) return return_iter finally: if hasattr(app_iter, 'close'): app_iter.close() except: exc_info = sys.exc_info() is_async = environ.get('is_async', None) == True content_type = is_async and 'application/json' or 'text/html' # Tell the Registry to save its StackedObjectProxies current state # for later restoration registry.restorer.save_registry_state(environ) count = get_debug_count(environ) view_uri = self.make_view_url(environ, base_path, count) if not started: headers = [('content-type', content_type)] headers.append(('X-Debug-URL', view_uri)) start_response('500 Internal Server Error', headers, exc_info) environ['wsgi.errors'].write('Debug at: %s\n' % view_uri) exc_data = collector.collect_exception(*exc_info) exc_data.view_url = view_uri if self.reporters: for reporter in self.reporters: reporter.report(exc_data) debug_info = DebugInfo(count, exc_info, exc_data, base_path, environ, view_uri, self.error_template, self.templating_formatters, self.head_html, self.footer_html, self.libraries) assert count not in self.debug_infos self.debug_infos[count] = debug_info if is_async: return [handle_async_exception(exc_info, environ, debug_info=debug_info)] # @@: it would be nice to deal with bad content types here return debug_info.content()