Skip to content

fix(response): handle generic PSR-7 bodies in JsonResponse - #17

Merged
coisa merged 1 commit into
mainfrom
fix/json-response-generic-body
Oct 24, 2026
Merged

coisa merged 1 commit into
mainfrom
fix/json-response-generic-body

Conversation

@coisa

@coisa coisa commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Preserve original PayloadStreamInterface behavior, including JsonStream encoding options.
  • Decode a generic readable/seekable PSR-7 body as associative JSON and restore its cursor even if decoding fails.
  • Throw explicit JsonException for invalid JSON and RuntimeException for detached/unreadable/non-seekable generic bodies rather than consuming them or calling nonexistent methods.
  • Allow withPayload() to replace any generic body with a new JsonStream while preserving response headers/status; a generic body has no recoverable JsonStream encoding options, so defaults apply.
  • Remove the inaccurate getBody() annotation that narrowed the inherited PSR-7 contract.

Closes #13

Validation

Three regressions reproduced undefined-method errors before the change. 11 JsonResponse tests / 32 assertions pass on PHP 8.4.26 with PHPUnit 12.5.38 and an isolated bootstrap using existing Nyholm/PSR source. Covers valid JSON, null, invalid JSON, detached/non-seekable bodies, cursor preservation, immutability and existing encoding options/headers. PHP lint, diff whitespace checks and composer validate --strict passed.

Full DevTools suite is not claimed: development dependencies are incomplete and the previously blocked download was not retried. The broader source-based suite reaches a known missing Symfony Process dependency in ConsumerSkillTest. PHP 8.3 was not executed locally.

For maintainer review; no merge or release.

GitHub-hosted CI follow-up

The test workflow completed successfully on PHP 8.3, 8.4 and 8.5. The PHP 8.3 job log confirms 189 tests / 298 assertions (8 existing PHPUnit notices), with the PHPUnit execution step successful (not merely a published status). Changelog, Reports and Wiki PR workflows also completed successfully. Local dependency limitations above do not describe the hosted runner. Published sources were read back and match the locally tested files byte-for-byte.

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Improved JsonResponse handling for JSON payloads provided through generic PSR-7 response bodies.
    • Payloads are decoded reliably while preserving the body’s current reading position.
    • Added clearer errors for invalid JSON, detached streams, unreadable bodies, and non-seekable streams.
    • JSON null is handled correctly.
    • Replacing payloads now preserves existing encoding options and response headers.

JsonResponse::getPayload() now decodes supported generic streams while preserving their cursor. withPayload() can replace a generic body with a JsonStream. Tests cover stream errors, JSON null, cursor behavior, and preservation of response data.

Changes: JsonResponse generic body support

Layer / File(s) Summary
Generic body payload access
src/JsonResponse.php, tests/JsonResponseTest.php
The body documentation now permits any StreamInterface. getPayload() reads generic bodies only when they are readable and seekable, decodes JSON with exceptions enabled, and restores the cursor. Tests cover valid JSON, invalid JSON, null, detached streams, and non-seekable streams.
Payload replacement
src/JsonResponse.php, tests/JsonResponseTest.php, .changelog/json-response-body.md
withPayload() uses the payload-stream method when available and creates a new JsonStream for a generic body. Tests cover replacement, encoding options, headers, and the original response. The changelog records the behavior and stream errors.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Merge Risk: ⚪ Minimal · up to 95679

The change is mergeable after normal checks; no concrete blocking issue remains.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 2 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely identifies the main change: handling generic PSR-7 bodies in JsonResponse.
Description check Passed The description directly explains generic body decoding, error handling, payload replacement, preserved headers and status, validation results, and known test limitations.
Linked Issues check Passed Issue #13 requires valid payload methods after PSR-7 withBody() replacement, generic-body interpretation, withPayload() replacement, immutability, and tests for valid, invalid, and detached streams. s…
Out of Scope Changes check Passed The reviewed changes are limited to JsonResponse generic-body handling, its focused JsonResponse tests, and a patch changelog entry. The tests and changelog support the implementation for issue #13. N…
Full details: Linked Issues check

Explanation

Issue #13 requires valid payload methods after PSR-7 withBody() replacement, generic-body interpretation, withPayload() replacement, immutability, and tests for valid, invalid, and detached streams. src/JsonResponse.php documents that a replaced body may be any StreamInterface. getPayload() returns payloads from PayloadStreamInterface and decodes readable, seekable generic bodies with JSON exceptions while restoring the cursor. It throws RuntimeException for unreadable, detached, or non-seekable bodies. withPayload() creates a new JsonStream for generic bodies and retains the original response. JsonResponseTest.php covers valid JSON, invalid JSON, detached and non-seekable bodies, cursor preservation, replacement, and immutability.

Full details: Out of Scope Changes check

Explanation

The reviewed changes are limited to JsonResponse generic-body handling, its focused JsonResponse tests, and a patch changelog entry. The tests and changelog support the implementation for issue #13. No unrelated behavior or files are evident.

Full details: Docstring Coverage

Explanation

Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 2 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit reads the stream with care
And keeps its cursor resting there
If JSON fails, an error shows
A fresh JsonStream can replace what flows
The headers stay, the old response remains
Then off the rabbit hops through JSON lanes

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-21T18:10:47.700981Z 956798e PR opened
🔒 Security Review ⚠️ Failed 2026-10-21T18:09:42.529739Z
We couldn’t complete this review. Comment @codex security review to try again.
956798e PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown
Contributor

Changelog

✅ Contribution check passed.

Head: 956798ed41aacd550763279b5380cb1ee72ea679

Base: b2129a2e33ebb69ee715809afa5d375bf78b4b4b

Contribution: 1 new valid fragment(s). Policy: ordinary.

  • json-response-body.md — fixed, patch

    Keep JsonResponse payload access and replacement usable after a generic PSR-7 body replacement, with explicit decoding and stream errors.

coisa commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

The previous attempt was rate-limited and its stated reset window has elapsed. Please review the current JsonResponse body-interoperability changes on 956798e.

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔇 Additional comments: 3
src/JsonResponse.php: 1

31-31: LGTM!

Also applies to: 58-85, 101-104

tests/JsonResponseTest.php: 1

134-206: LGTM!

.changelog/json-response-body.md-6-6: 1

6-6: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

⚠️ Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.

Add a top-level Markdown heading.

markdownlint-cli2 reports MD041 because the changelog has no H1 after its front matter. Add a heading before the description.

Proposed fix
 ---
 category: fixed
 type: patch
 ---
 
+# Generic body support in `JsonResponse`
+
 Keep JsonResponse payload access and replacement usable after a generic PSR-7 body replacement, with explicit decoding and stream errors.

Source: Linters/SAST tools


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 01d04461-4bc4-4563-8bab-d4549480baf9
📥 Commits

Reviewing files that changed from the base of the PR and between b2129a2 and 956798e.

📒 Files selected for processing: 3
  • .changelog/json-response-body.md
  • src/JsonResponse.php
  • tests/JsonResponseTest.php

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@coisa
coisa merged commit 0e80ba7 into main Oct 24, 2026
35 checks passed
@coisa
coisa deleted the fix/json-response-generic-body branch October 24, 2026 02:28
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.

fix(response): keep payload methods valid after PSR-7 withBody replacement

1 participant