diff --git a/inference/core/interfaces/http/http_api.py b/inference/core/interfaces/http/http_api.py index 01ccd55570..406549811d 100644 --- a/inference/core/interfaces/http/http_api.py +++ b/inference/core/interfaces/http/http_api.py @@ -716,6 +716,16 @@ def _authorization_error_response(status_code: int, msg: str): 402, cached_api_keys[api_key].message, ) + else: + logger.warning( + "Unexpected status %s from serverless usage check; " + "failing closed without caching.", + usage_check_result.status_code, + ) + return _authorization_error_response( + 503, + "Authorization service temporarily unavailable. Please retry.", + ) response = await call_next(request) if workspace_id: diff --git a/tests/inference/unit_tests/core/interfaces/http/test_http_api.py b/tests/inference/unit_tests/core/interfaces/http/test_http_api.py index 827a4c3468..36f035877e 100644 --- a/tests/inference/unit_tests/core/interfaces/http/test_http_api.py +++ b/tests/inference/unit_tests/core/interfaces/http/test_http_api.py @@ -98,9 +98,7 @@ def test_infer_lmm_with_model_id_uses_alias_registry_key(monkeypatch) -> None: service_secret=None, ) model_manager.infer_from_request_sync.assert_called_once() - assert ( - model_manager.infer_from_request_sync.call_args.args[0] == "florence-2-base" - ) + assert model_manager.infer_from_request_sync.call_args.args[0] == "florence-2-base" inference_request = model_manager.infer_from_request_sync.call_args.args[1] assert inference_request.model_id == "florence-2-base" assert inference_request.api_key == "query-api-key" @@ -204,3 +202,36 @@ def test_serverless_auth_middleware_caches_payment_required_response( assert usage_check_mock.await_count == 1 model_manager.add_model.assert_not_called() model_manager.infer_from_request_sync.assert_not_called() + + +def test_serverless_auth_middleware_fails_closed_on_unexpected_upstream_status( + monkeypatch, +) -> None: + interface, model_manager, usage_check_mock = _build_serverless_interface( + monkeypatch=monkeypatch, + usage_check_result=ServerlessUsageCheckResponse(status_code=503), + ) + + with TestClient(interface.app) as client: + first_response = client.post( + "/infer/lmm/florence-2-base", + params={"api_key": "query-api-key"}, + json=_make_inference_request(), + ) + second_response = client.post( + "/infer/lmm/florence-2-base", + params={"api_key": "query-api-key"}, + json=_make_inference_request(), + ) + + assert first_response.status_code == 503 + assert second_response.status_code == 503 + assert ( + first_response.json()["message"] + == "Authorization service temporarily unavailable. Please retry." + ) + assert WORKSPACE_ID_HEADER not in first_response.headers + # Unexpected upstream statuses must not be cached, so every request re-queries. + assert usage_check_mock.await_count == 2 + model_manager.add_model.assert_not_called() + model_manager.infer_from_request_sync.assert_not_called()