diff --git a/datadog_lambda/wrapper.py b/datadog_lambda/wrapper.py index d022988b..8db0d247 100644 --- a/datadog_lambda/wrapper.py +++ b/datadog_lambda/wrapper.py @@ -188,7 +188,6 @@ def __call__(self, event, context, **kwargs): if self.blocking_response: return self.blocking_response self.response = self.func(event, context, **kwargs) - return self.response except BlockingException: self.blocking_response = get_asm_blocked_response(self.event_source) except Exception: @@ -201,8 +200,10 @@ def __call__(self, event, context, **kwargs): raise finally: self._after(event, context) - if self.blocking_response: - return self.blocking_response + + if self.blocking_response: + return self.blocking_response + return self.response def _inject_authorizer_span_headers(self, request_id): reference_span = self.inferred_span if self.inferred_span else self.span diff --git a/tests/test_wrapper.py b/tests/test_wrapper.py index 5b2afea8..b1aa1ae8 100644 --- a/tests/test_wrapper.py +++ b/tests/test_wrapper.py @@ -765,6 +765,23 @@ def lambda_handler(event, context): assert lambda_handler.span.get_tag("http.status_code") == "403" + def test_handler_exception_propagates_when_appsec_enabled(self): + # Regression guard: before the fix, `return` in the `finally` block + # would silently swallow handler exceptions when no blocking response + # was set, preventing them from reaching the caller. + self.mock_get_asm_blocking_response.return_value = None + + class HandlerError(Exception): + pass + + def lambda_handler(event, context): + raise HandlerError("handler error") + + lambda_handler = wrapper.datadog_lambda_wrapper(lambda_handler) + + with self.assertRaises(HandlerError): + lambda_handler(self.api_gateway_request, get_mock_context()) + def test_no_blocking_appsec_disabled(self): os.environ["DD_APPSEC_ENABLED"] = "false"