# (c) 2009-2024 Martin Wendt and contributors; see WsgiDAV https://github.com/mar10/wsgidav# Original PyFileServer (c) 2005 Ho Chun Wei.# Licensed under the MIT license:# http://www.opensource.org/licenses/mit-license.php"""WSGI middleware to catch application thrown DAVErrors and return properresponses."""importtracebackfromwsgidavimportutilfromwsgidav.dav_errorimport(HTTP_INTERNAL_ERROR,HTTP_NO_CONTENT,HTTP_NOT_MODIFIED,DAVError,as_DAVError,get_http_status_string,)fromwsgidav.mw.base_mwimportBaseMiddleware__docformat__="reStructuredText"_logger=util.get_module_logger(__name__)# ========================================================================# ErrorPrinter# ========================================================================
[docs]def__call__(self,environ,start_response):# Intercept start_responsesub_app_start_response=util.SubAppStartResponse()try:try:# request_server app may be a generator (for example the GET handler)# So we must iterate - not return self.next_app(..)!# Otherwise the we could not catch exceptions here.response_started=Falseapp_iter=self.next_app(environ,sub_app_start_response)forvinapp_iter:# Start response (the first time)ifnotresponse_started:# Success!start_response(sub_app_start_response.status,sub_app_start_response.response_headers,sub_app_start_response.exc_info,)response_started=Trueyieldv# Close out iteratorifhasattr(app_iter,"close"):app_iter.close()# Start response (if it hasn't been done yet)ifnotresponse_started:# Success!start_response(sub_app_start_response.status,sub_app_start_response.response_headers,sub_app_start_response.exc_info,)returnexceptDAVError:raise# Deliberately generated or already convertedexceptExceptionase:# Caught a non-DAVError# Catch all exceptions to return as 500 Internal Error_logger.error(f"{traceback.format_exc(10)}")raiseas_DAVError(e)fromNoneexceptDAVErrorase:_logger.debug(f"Caught {e}")status=get_http_status_string(e)# Dump internal errors to consoleife.value==HTTP_INTERNAL_ERROR:tb=traceback.format_exc(10)_logger.error(f"Caught HTTPRequestException(HTTP_INTERNAL_ERROR)\n{tb}")# traceback.print_exc(10, environ.get("wsgi.errors") or sys.stdout)_logger.error(f"e.src_exception:\n{e.src_exception}")elife.valuein(HTTP_NOT_MODIFIED,HTTP_NO_CONTENT):# _logger.warning("Forcing empty error response for {}".format(e.value))# See paste.lint: these code don't have contentstart_response(status,[("Content-Length","0"),("Date",util.get_rfc1123_time())])yieldb""return# If exception has pre-/post-condition: return as XML response,# else return as HTMLcontent_type,body=e.get_response_page()headers=e.add_headersor[]# TODO: provide exc_info=sys.exc_info()?start_response(status,[("Content-Type",content_type),("Content-Length",str(len(body))),("Date",util.get_rfc1123_time()),]+headers,)yieldbodyreturn