Skip to content

fix(dispatch): stop misreading list/dict handler returns as raw bytes/wrong status - #233

Merged
ZhuchkaTriplesix merged 1 commit into
devfrom
issue-211-fix-list-dict-handler-return
Sep 29, 2026
Merged

ZhuchkaTriplesix merged 1 commit into
devfrom
issue-211-fix-list-dict-handler-return

Conversation

@ZhuchkaTriplesix

Copy link
Copy Markdown
Member

Problem

map_handler_return() tried extract::<Vec<u8>>() before checking for a plain dict/list. pyo3 happily extracts any Python sequence of small ints as Vec<u8> — including an empty list — so:

  • return [] sent an empty application/octet-stream body instead of JSON [].
  • return [1, 2, 3] sent raw bytes \x01\x02\x03 instead of JSON [1,2,3].

Separately, any dict containing both a status and body key was unconditionally treated as a structured HTTP response — so ordinary JSON data shaped that way (e.g. {"status": 1, "body": "x"}) had its HTTP status silently set to 1 instead of being returned as data.

Fix

  • Check for PyDict/PyList before the String/Vec<u8> extraction attempts, so JSON payloads always fall through to JSON serialization instead of being coerced to bytes.
  • Require status to be a plausible HTTP status code (100-599, RFC 9110 §15) before treating a dict as a structured response — preserves the existing documented {"status": ..., "body": ...} shorthand (docs/usage.md, tests/test_exception_handlers.py) for real status codes, while letting ambiguous data round-trip as JSON.

Testing

New tests/test_handler_return_mapping.py:

  • test_empty_list_is_json_not_octet_stream

  • test_int_list_is_json_not_raw_bytes

  • test_dict_with_out_of_range_status_roundtrips_as_data

  • test_dict_with_valid_status_and_body_is_still_a_structured_response (confirms the documented shorthand still works)

  • cargo build --lib / cargo clippy --all-targets: clean.

  • cargo test --lib: 26 passed.

  • Full suite: 168 passed (164 + 4 new), 1 skipped.

  • ruff check / ruff format --check: clean.

Closes #211

…/wrong status

map_handler_return() tried extract::<Vec<u8>>() before checking for a
plain dict/list. pyo3 happily extracts any Python sequence of small
ints as Vec<u8> - including an empty list - so `return []` sent an
empty application/octet-stream body instead of JSON `[]`, and
`return [1, 2, 3]` sent raw bytes \x01\x02\x03 instead of JSON
`[1,2,3]`.

Separately, any dict containing both a "status" and "body" key was
unconditionally treated as a structured HTTP response, so ordinary
JSON data shaped that way (e.g. {"status": 1, "body": "x"}) had its
HTTP status silently set to 1 instead of being returned as data.

Fix:
- Check for PyDict/PyList before the String/Vec<u8> extraction
  attempts, so JSON payloads always fall through to JSON
  serialization instead of being coerced to bytes.
- Require "status" to be a plausible HTTP status code (100-599,
  RFC 9110 Sec 15) before treating a dict as a structured response,
  preserving the existing documented {"status": ..., "body": ...}
  shorthand (docs/usage.md, tests/test_exception_handlers.py) for
  real status codes while letting ambiguous data round-trip as JSON.

Closes #211
@ZhuchkaTriplesix
ZhuchkaTriplesix merged commit 8bc5931 into dev Sep 29, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant