diff --git a/frappe/__init__.py b/frappe/__init__.py index d8545624c06..f72ae436b09 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -179,9 +179,9 @@ def set_user_lang(user, user_language=None): # end: static analysis hack -def init(site, sites_path=None, new_site=False): +def init(site, sites_path=".", new_site=False, force=False): """Initialize frappe for the current site. Reset thread locals `frappe.local`""" - if getattr(local, "initialised", None): + if getattr(local, "initialised", None) and not force: return if not sites_path: diff --git a/frappe/app.py b/frappe/app.py index 33648c77541..93ab4fd2e38 100644 --- a/frappe/app.py +++ b/frappe/app.py @@ -90,12 +90,18 @@ def application(request): rollback = after_request(rollback) finally: + # Important note: + # this function *must* always return a response, hence any exception thrown outside of + # try..catch block like this finally block needs to be handled appropriately. + if request.method in ("POST", "PUT") and frappe.db and rollback: frappe.db.rollback() - if getattr(frappe.local, "initialised", False): - for after_request_task in frappe.get_hooks("after_request"): - frappe.call(after_request_task, response=response, request=request) + try: + run_after_request_hooks(request, response) + except Exception as e: + # We can not handle exceptions safely here. + frappe.logger().error("Failed to run after request hook", exc_info=True) log_request(request, response) process_response(response) @@ -104,12 +110,20 @@ def application(request): return response +def run_after_request_hooks(request, response): + if not getattr(frappe.local, "initialised", False): + return + + for after_request_task in frappe.get_hooks("after_request"): + frappe.call(after_request_task, response=response, request=request) + + def init_request(request): frappe.local.request = request frappe.local.is_ajax = frappe.get_request_header("X-Requested-With") == "XMLHttpRequest" site = _site or request.headers.get("X-Frappe-Site-Name") or get_site_name(request.host) - frappe.init(site=site, sites_path=_sites_path) + frappe.init(site=site, sites_path=_sites_path, force=True) if not (frappe.local.conf and frappe.local.conf.db_name): # site does not exist