Skip to content

feat(web): HTTP message converter chain — JSON/XML content negotiation, read+write (v26.06.28)#53

Merged
ancongui merged 1 commit into
mainfrom
feat/http-message-converters
Jun 7, 2026
Merged

feat(web): HTTP message converter chain — JSON/XML content negotiation, read+write (v26.06.28)#53
ancongui merged 1 commit into
mainfrom
feat/http-message-converters

Conversation

@ancongui
Copy link
Copy Markdown
Contributor

@ancongui ancongui commented Jun 7, 2026

Summary

Completes Jackson parity — the HttpMessageConverter model. Serialization is now a pluggable, ordered converter chain selected by media type for both read and write.

  • MessageConverter + JsonMessageConverter / XmlMessageConverter (both backed by PyFlyJsonSerializer, so pyfly.web.json.* config applies to every format) + MessageConverterRegistry (ordered; user converters take priority — register a MessageConverterRegistry bean to add CBOR/etc.).
  • Real content negotiation: responses chosen from Accept with q-values; requests from Content-Type.
  • XML request bodies now deserialize into models (was response-only / JSON-only reads).
  • fail-on-unknown-properties enforced on read via a cached extra='forbid' overlay (no model mutation).
  • Exported from pyfly.web; wired through the controller response path + resolver body path (both Starlette & FastAPI).

Tests

  • test_message_converters.py (7): parse_accept q-values, JSON/XML roundtrip, fail-on-unknown, registry negotiation, custom-converter priority, response negotiation.
  • test_content_negotiation_e2e.py (2): real controller via TestClient — GET negotiates JSON⇄XML by Accept; POST parses JSON and XML bodies.
  • Updated test_response.py to assert media-type/body rather than the concrete Response class.

Gates

mypy --strict (611) ✓ · ruff + ruff format ✓ · full suite 3766 passed, 1 skipped.

Bumps v26.06.27 → v26.06.28. Not built (noted): per-route produces/consumes. Next: Wave 4 (multi-datasource, SpEL, Testcontainers) + Wave 5 (docs + skills/agents).

…n (read+write) + bump v26.06.28

Completes Jackson parity (the HttpMessageConverter model):
- MessageConverter base + JsonMessageConverter/XmlMessageConverter (both via PyFlyJsonSerializer
  so pyfly.web.json.* applies to every format) + MessageConverterRegistry (ordered, user converters
  take priority via a MessageConverterRegistry bean).
- Content negotiation: responses select by Accept (q-value ordered, JSON default); requests by
  Content-Type. XML REQUEST bodies now deserialize into models (was response-only, JSON-only reads).
- fail-on-unknown-properties enforced on read via a cached extra='forbid' overlay (no model mutation).
- Wired through controller response path + resolver body path; exported from pyfly.web.

Tests: test_message_converters.py (7) + test_content_negotiation_e2e.py (2, real controller via
TestClient: JSON<->XML response + XML request parsing); updated test_response.py to assert
media-type/body not the concrete Response class. Gates: mypy --strict (611), ruff + format,
full suite 3766 passed.
@ancongui ancongui merged commit 53ddbd3 into main Jun 7, 2026
5 checks passed
@ancongui ancongui deleted the feat/http-message-converters branch June 7, 2026 09:07
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