Where: src/dispatch.rs:1336-1402 (map_handler_return).
For the common case of a handler returning a dict/list, the current order is: try getattr("__oxyroute_stream_done__") (raises a real AttributeError on plain dicts — exception machinery on every JSON response), then several failed extract attempts, then get_item calls, then falls through to py.import("json").call_method1("dumps", ...).
Fix direction: check PyDict/PyList early (right after the str/bytes fast paths) and serialize directly in Rust by walking the Python object into a serde_json::Value/writer instead of round-tripping through json.dumps. This is likely the single biggest win for typical JSON-API workloads; also fixes the list-response correctness issue (#211).
Where:
src/dispatch.rs:1336-1402(map_handler_return).For the common case of a handler returning a
dict/list, the current order is: trygetattr("__oxyroute_stream_done__")(raises a realAttributeErroron plain dicts — exception machinery on every JSON response), then several failedextractattempts, thenget_itemcalls, then falls through topy.import("json").call_method1("dumps", ...).Fix direction: check
PyDict/PyListearly (right after the str/bytes fast paths) and serialize directly in Rust by walking the Python object into aserde_json::Value/writer instead of round-tripping throughjson.dumps. This is likely the single biggest win for typical JSON-API workloads; also fixes the list-response correctness issue (#211).