doesnt throw if not json
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from json import JSONDecodeError
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
@@ -82,14 +83,16 @@ async def call_openapi_operation(
|
|||||||
if close_client:
|
if close_client:
|
||||||
await active_client.aclose()
|
await active_client.aclose()
|
||||||
|
|
||||||
body = _response_body(response)
|
body, body_errors = _response_body(response)
|
||||||
headers = {str(key): str(value) for key, value in response.headers.items()}
|
headers = {str(key): str(value) for key, value in response.headers.items()}
|
||||||
output = OpenApiOperationOutput(
|
output = OpenApiOperationOutput(
|
||||||
status_code=response.status_code,
|
status_code=response.status_code,
|
||||||
headers=headers,
|
headers=headers,
|
||||||
body=body,
|
body=body,
|
||||||
validation_errors=[],
|
validation_errors=body_errors,
|
||||||
)
|
)
|
||||||
|
if body_errors:
|
||||||
|
return NodeReturn(outcome="validation_error", output=output)
|
||||||
|
|
||||||
if not _status_declared(operation, response.status_code):
|
if not _status_declared(operation, response.status_code):
|
||||||
output.validation_errors = [
|
output.validation_errors = [
|
||||||
@@ -134,13 +137,17 @@ async def _send_request(
|
|||||||
return await client.request(**kwargs)
|
return await client.request(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def _response_body(response: httpx.Response) -> Any:
|
def _response_body(response: httpx.Response) -> tuple[Any, list[str]]:
|
||||||
|
"""Parse response body while keeping malformed JSON in validation flow."""
|
||||||
content_type = response.headers.get("content-type", "").lower()
|
content_type = response.headers.get("content-type", "").lower()
|
||||||
if not response.content:
|
if not response.content:
|
||||||
return None
|
return None, []
|
||||||
if "json" in content_type:
|
if "json" in content_type:
|
||||||
return response.json()
|
try:
|
||||||
return response.text
|
return response.json(), []
|
||||||
|
except JSONDecodeError as exc:
|
||||||
|
return response.text, [str(exc)]
|
||||||
|
return response.text, []
|
||||||
|
|
||||||
|
|
||||||
def _status_declared(operation: OpenApiOperation, status_code: int) -> bool:
|
def _status_declared(operation: OpenApiOperation, status_code: int) -> bool:
|
||||||
|
|||||||
@@ -149,6 +149,39 @@ def test_call_openapi_operation_maps_invalid_response_to_validation_error() -> N
|
|||||||
assert result.output.validation_errors
|
assert result.output.validation_errors
|
||||||
|
|
||||||
|
|
||||||
|
def test_call_openapi_operation_maps_malformed_json_response_to_validation_error() -> (
|
||||||
|
None
|
||||||
|
):
|
||||||
|
app = load_openapi_app(FIXTURE)
|
||||||
|
operation = next(
|
||||||
|
op for op in load_openapi_operations(FIXTURE) if op.name == "get_pet"
|
||||||
|
)
|
||||||
|
|
||||||
|
async def handler(request: httpx.Request) -> httpx.Response:
|
||||||
|
_ = request
|
||||||
|
return httpx.Response(
|
||||||
|
200,
|
||||||
|
headers={"content-type": "application/json"},
|
||||||
|
content=b"{not json",
|
||||||
|
)
|
||||||
|
|
||||||
|
async def run() -> NodeReturn[OpenApiOperationOutput]:
|
||||||
|
async with httpx.AsyncClient(transport=httpx.MockTransport(handler)) as client:
|
||||||
|
return await call_openapi_operation(
|
||||||
|
app,
|
||||||
|
operation,
|
||||||
|
OpenApiExecutionConfig(base_url="https://api.example.test"),
|
||||||
|
{"path": {"petId": "pet-1"}},
|
||||||
|
client=client,
|
||||||
|
)
|
||||||
|
|
||||||
|
result = asyncio.run(run())
|
||||||
|
|
||||||
|
assert result.outcome == "validation_error"
|
||||||
|
assert result.output.status_code == 200
|
||||||
|
assert result.output.validation_errors
|
||||||
|
|
||||||
|
|
||||||
def test_call_openapi_operation_maps_transport_error() -> None:
|
def test_call_openapi_operation_maps_transport_error() -> None:
|
||||||
app = load_openapi_app(FIXTURE)
|
app = load_openapi_app(FIXTURE)
|
||||||
operation = next(
|
operation = next(
|
||||||
|
|||||||
Reference in New Issue
Block a user