Skip to content

fix(SSE-text/event-stream): sse response body is empty in res.getBody() for app and cli#8212

Open
sachin-thakur-bruno wants to merge 2 commits into
usebruno:mainfrom
sachin-thakur-bruno:bugfix/sse-script-response-body
Open

fix(SSE-text/event-stream): sse response body is empty in res.getBody() for app and cli#8212
sachin-thakur-bruno wants to merge 2 commits into
usebruno:mainfrom
sachin-thakur-bruno:bugfix/sse-script-response-body

Conversation

@sachin-thakur-bruno

@sachin-thakur-bruno sachin-thakur-bruno commented Jun 9, 2026

Copy link
Copy Markdown

Description

JIRA

Bug

The desktop app always requests responses as a stream
(responseType: 'stream'). For non-streaming responses it drains the stream
into a full buffer via promisifyStream before running post-response logic.

For SSE responses, the single-request path deliberately skips that drain so
chunks can be forwarded to the renderer live, and hard-codes the body to empty:

The streamed chunks were forwarded to the renderer for the live view and then
discarded — nothing ever reconstituted them into response.data. So when
post-response scripts, assertions, and tests ran on the stream's close event,
they read an empty body.

Fix

Accumulate the streamed chunks (in the existing renderer-forwarding data
listener — the single stream consumer) and, on stream close, rebuild
response.data / response.dataBuffer from them before running
post-response scripts. This mirrors what the Collection Runner already does,
without adding a second stream listener (which would change flowing-mode timing
and risk dropping early chunks from the live UI).

All changes are in packages/bruno-electron/src/ipc/network/index.js:

Contribution Checklist:

  • I've used AI significantly to create this pull request
  • The pull request only addresses one issue or adds one feature.
  • The pull request does not introduce any breaking changes
  • I have added screenshots or gifs to help explain the change if applicable.
  • I have read the contribution guidelines.
  • Create an issue and link to the pull request.

Note: Keeping the PR small and focused helps make it easier to review and merge. If you have multiple changes you want to make, please consider submitting them as separate pull requests.

Publishing to New Package Managers

Please see here for more information.

Summary by CodeRabbit

  • Bug Fixes
    • Streaming responses now buffer and reconstruct streamed data when the stream closes, ensuring complete response content is available.
    • Post-processing is applied to the reconstructed body and the returned payload now includes the buffered chunks for streamed responses, improving reliability for server-sent events and streaming interactions.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 56dcc445-8bbb-4c2b-a51f-f0231a245deb

📥 Commits

Reviewing files that changed from the base of the PR and between 9f5b969 and 4f5c96e.

📒 Files selected for processing (1)
  • packages/bruno-electron/src/ipc/network/index.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/bruno-electron/src/ipc/network/index.js

Walkthrough

This PR updates the Electron IPC network SSE/response-stream flow to buffer raw streamed chunks into response.sseChunks, append chunks on 'data' events, concatenate and parse them into response.data/response.dataBuffer on stream 'close', then run post-scripts; the returned streaming response now includes sseChunks.

Changes

SSE Stream Chunk Accumulation

Layer / File(s) Summary
Stream chunk lifecycle and response reconstruction
packages/bruno-electron/src/ipc/network/index.js
Initializes sseChunks when the response starts, appends raw chunks on streaming 'data' events, concatenates and parses collected chunks on 'close' into response.data/response.dataBuffer via parseDataFromResponse, invokes runPostScripts(), and exposes sseChunks in the returned response object.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • usebruno/bruno#6862: Also modifies packages/bruno-electron/src/ipc/network/index.js stream handling to avoid premature truncation and accumulate full streamed data before parsing.
  • usebruno/bruno#6569: Changes SSE streaming path to add per-chunk metadata and adjust close-event handling related to how chunks are accumulated and parsed.

Suggested labels

size/L

Suggested reviewers

  • helloanoop
  • lohit-bruno
  • naman-bruno
  • bijin-bruno

Poem

Streams arrive in bits and beats,
Gathered patient, stitched in sheets,
On the close the pieces meet,
Parsed and whole, the response complete,
Small chunks become a single feat. 🎐

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main fix: buffering SSE response chunks to populate the response body for post-response logic in desktop app and CLI.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

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

@sachin-thakur-bruno sachin-thakur-bruno changed the title fix(SSE-text/event-stream): response body is empty in res.getBody() for app and cli fix(SSE-text/event-stream): sse response body is empty in res.getBody() for app and cli Jun 9, 2026
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":500,"request":{"method":"PATCH","url":"https://api.github.com/repos/usebruno/bruno/issues/comments/4659649601","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","authorization":"token [REDACTED]","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- review_stack_entry_start -->\n\n[![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/usebruno/bruno/pull/8212?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)\n\n<!-- review_stack_entry_end -->\n<!-- This is an auto-generated comment: review in progress by coderabbit.ai -->\n\n> [!NOTE]\n> Currently processing new changes in this PR. This may take a few minutes, please wait...\n> \n> <details>\n> <summary>⚙️ Run configuration</summary>\n> \n> **Configuration used**: Path: .coderabbit.yaml\n> \n> **Review profile**: CHILL\n> \n> **Plan**: Pro\n> \n> **Run ID**: `c4269bda-2b56-4bf6-b6af-6e95ab316e4d`\n> \n> </details>\n> \n> <details>\n> <summary>📥 Commits</summary>\n> \n> Reviewing files that changed from the base of the PR and between 13a48a256fc62c874c151b48052d114b0fb7da56 and 9f5b9697d67a272a350948ae90885b459aacad09.\n> \n> </details>\n> \n> <details>\n> <summary>📒 Files selected for processing (1)</summary>\n> \n> * `packages/bruno-electron/src/ipc/network/index.js`\n> \n> </details>\n> \n> ```ascii\n>  ___________________________________________________________________________________________________________________________________________________________\n> < Don't be a slave to formal methods. Don't blindly adopt any technique without putting it into the context of your development practices and capabilities. >\n>  -----------------------------------------------------------------------------------------------------------------------------------------------------------\n>   \\\n>    \\   \\\n>         \\ /\\\n>         ( )\n>       .( o ).\n> ```\n\n<!-- end of auto-generated comment: review in progress by coderabbit.ai -->\n\n<!-- finishing_touch_checkbox_start -->\n\n<details>\n<summary>✨ Finishing Touches</summary>\n\n<details>\n<summary>🧪 Generate unit tests (beta)</summary>\n\n- [ ] <!-- {\"checkboxId\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Create PR with unit tests\n\n</details>\n\n</details>\n\n<!-- finishing_touch_checkbox_end -->\n<!-- tips_start -->\n\n---\n\nThanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=usebruno/bruno&utm_content=8212)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.\n\n<details>\n<summary>❤️ Share</summary>\n\n- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)\n- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)\n- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)\n- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)\n\n</details>\n\n\n<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>\n\n<!-- tips_end -->\n<!-- usage_tips_start -->\n\n> [!TIP]\n> <details>\n> <summary>CodeRabbit can use oxc to improve the quality of JavaScript and TypeScript code reviews.</summary>\n> \n> Add a [configuration file](https://github.com/oxc-project/oxc) to your project to customize how CodeRabbit runs oxc.\n> \n> </details>\n\n<!-- usage_tips_end -->"},"request":{"retryCount":3,"signal":{},"retries":3,"retryAfter":16}}}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/bruno-electron/src/ipc/network/index.js (1)

1017-1017: Consider memory implications for long-running SSE streams.

The sseChunks array accumulates all chunks for the entire duration of the stream without any size limits. For long-running SSE connections or high-throughput streams, this could lead to significant memory consumption.

While this is acceptable for typical SSE use cases, consider whether:

  • A maximum size threshold or warning is warranted for production deployments
  • The collected chunks could be periodically flushed or limited (though this might conflict with the goal of providing the full body to post-scripts)

This is primarily an operational consideration rather than a functional defect.

Also applies to: 1348-1349

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/bruno-electron/src/ipc/network/index.js` at line 1017, The sseChunks
array used to accumulate SSE data (referenced as sseChunks) can grow unbounded;
add a configurable cap (e.g., MAX_SSE_BUFFER_SIZE) and enforce it in the code
that appends to sseChunks (the SSE data handler function where sseChunks.push is
used) so that when the cap is exceeded you either drop oldest segments, stop
buffering and log a warning via the existing logger, or flush the buffer to a
temporary store; also expose the cap as a config/env variable and apply the same
safeguard to the other occurrence noted around lines 1348-1349 so
long-running/high-throughput streams won’t cause unbounded memory growth.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/bruno-electron/src/ipc/network/index.js`:
- Around line 1247-1258: The close event handler must guard against exceptions
from Buffer.concat and parseDataFromResponse and handle rejections from
runPostScripts: wrap the SSE reconstruction logic (the Buffer.concat(...) and
parseDataFromResponse(...) calls) in a try-catch that logs the error and
performs any necessary cleanup/rejects the related promise, and change the
runPostScripts().then(...) call to include a .catch(...) (or use await with
try-catch) that logs the error and prevents an unhandled rejection; reference
the close event handler and the functions runPostScripts, Buffer.concat, and
parseDataFromResponse when making these changes.
- Around line 1348-1349: The SSE handler currently uses optional chaining with
response.sseChunks?.push(newData) which will silently drop chunks if
response.sseChunks is unset; ensure response.sseChunks is initialized before the
handler runs (e.g., set response.sseChunks = [] where the response is created)
or add an explicit fallback/assertion in the handler (e.g., if
(!response.sseChunks) throw or assign an empty array before calling push) so
chunks are never lost silently; locate the code that references
response.sseChunks?.push(newData) and either initialize response.sseChunks at
creation or replace the optional push with a guarded push/assertion to catch
misconfiguration.

---

Nitpick comments:
In `@packages/bruno-electron/src/ipc/network/index.js`:
- Line 1017: The sseChunks array used to accumulate SSE data (referenced as
sseChunks) can grow unbounded; add a configurable cap (e.g.,
MAX_SSE_BUFFER_SIZE) and enforce it in the code that appends to sseChunks (the
SSE data handler function where sseChunks.push is used) so that when the cap is
exceeded you either drop oldest segments, stop buffering and log a warning via
the existing logger, or flush the buffer to a temporary store; also expose the
cap as a config/env variable and apply the same safeguard to the other
occurrence noted around lines 1348-1349 so long-running/high-throughput streams
won’t cause unbounded memory growth.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c4269bda-2b56-4bf6-b6af-6e95ab316e4d

📥 Commits

Reviewing files that changed from the base of the PR and between 13a48a2 and 9f5b969.

📒 Files selected for processing (1)
  • packages/bruno-electron/src/ipc/network/index.js

Comment thread packages/bruno-electron/src/ipc/network/index.js
Comment thread packages/bruno-electron/src/ipc/network/index.js
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant