Skip to content

fix: broken sse event rendering in ui - #8763

Open
sammaji wants to merge 1 commit into
usebruno:mainfrom
sammaji:main
Open

fix: broken sse event rendering in ui#8763
sammaji wants to merge 1 commit into
usebruno:mainfrom
sammaji:main

Conversation

@sammaji

@sammaji sammaji commented Jul 24, 2026

Copy link
Copy Markdown

Description

Added sse-event-buffer.js (createSseEventBuffer), which buffers incoming bytes, decoding with StringDecoder so multi-byte UTF-8 characters are never split across chunks, and normalizing CRLF/CR line endings until a full SSE event (blank-line terminated) is available, only then handing it off to the renderer. flush() emits any trailing event left over when the stream closes without a final blank line. The send-http-request handler now pushes each chunk through this buffer instead of parsing raw chunks in isolation. The raw-byte accumulation used to rebuild the final persisted response body is untouched, so that stays byte-accurate.

Added unit tests in sse-event-buffer.spec.js covering: buffering until a full event arrives, reassembling a data: payload split mid-string (the reported bug), multiple events in one chunk, CRLF/CR normalization, multi-byte UTF-8 characters split across chunks, and flush() behavior.

Before:

Image Image

After:

Screenshot 2026-07-24 at 14 39 41 Screenshot 2026-07-24 at 14 39 58

Closes #8762

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.

Summary by CodeRabbit

  • Bug Fixes
    • Improved real-time SSE streaming by buffering incoming data until complete events are formed before dispatching to the renderer.
    • Improved handling of event boundaries across chunk splits, including \r\n/\r normalization and UTF-8 multi-byte boundaries.
    • Flushes any remaining buffered SSE content on connection close so no partial event is lost.
    • Enhanced behavior for SSE requests that connect successfully but don’t begin sending headers/stream within the expected timeout.
  • Tests
    • Added Jest coverage for SSE buffering, termination/flush behavior, encoding and boundary edge cases, plus end-to-end SSE timeout scenarios.

Copilot AI review requested due to automatic review settings July 24, 2026 09:05
@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

@sammaji is attempting to deploy a commit to the Bruno Team on Vercel.

A member of the Team first needs to authorize it.

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The network IPC SSE path now buffers streamed chunks, reconstructs complete events across boundaries, preserves UTF-8 data, dispatches sequenced events, and flushes trailing data on stream close. Jest coverage validates buffering and SSE initial-response timeout behavior.

Changes

SSE streaming

Layer / File(s) Summary
SSE buffer contract and validation
packages/bruno-electron/src/ipc/network/sse-event-buffer.js, packages/bruno-electron/src/ipc/network/sse-event-buffer.spec.js
Adds UTF-8-aware buffering, line-ending normalization, blank-line event extraction, partial-event retention, flushing, and corresponding Jest coverage.
Network stream integration
packages/bruno-electron/src/ipc/network/index.js
Routes chunks through the buffer, dispatches complete parsed events with sequence numbers, and emits trailing buffered data on stream close.
SSE timeout validation
packages/bruno-electron/src/ipc/network/sse-event-buffer.spec.js
Tests successful SSE response startup before timeout and abort behavior when response headers are delayed.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant HTTPStream
  participant sseEventBuffer
  participant sendSseEvent
  participant Renderer
  HTTPStream->>sseEventBuffer: Push streamed chunk
  sseEventBuffer->>sendSseEvent: Return complete SSE event
  sendSseEvent->>Renderer: Dispatch parsed sequenced event
  HTTPStream->>sseEventBuffer: Flush on close
  sseEventBuffer->>sendSseEvent: Return trailing event
Loading

Suggested reviewers: helloanoop

Poem

Chunks cross the wire,
Newlines gather events whole,
UTF-8 dances through,
The final stream bows softly—
SSE flows in sequence.

🚥 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 reflects the main fix: SSE event rendering.
Linked Issues check ✅ Passed The buffering and UTF-8-safe SSE parsing directly address #8762's requirements.
Out of Scope Changes check ✅ Passed The added timeout tests support the requested SSE first-chunk timeout behavior and don't introduce unrelated changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
🧪 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.

@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: 3

🤖 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/sse-event-buffer.js`:
- Around line 23-26: Update the flush function to preserve leading and trailing
whitespace in the decoded SSE payload, removing the trim() call from the
remaining-data calculation. Keep returning null only when no data remains, while
forwarding non-JSON payload strings unchanged through parseDataFromResponse.
- Around line 10-18: Normalize decoded SSE text only after appending it to the
existing buffer in push, so CRLF sequences split across chunks remain a single
newline; preserve lone-CR normalization. In
packages/bruno-electron/src/ipc/network/sse-event-buffer.js lines 10-18, update
push accordingly. In
packages/bruno-electron/src/ipc/network/sse-event-buffer.spec.js lines 40-45,
add regression coverage for data: 1\r followed by \n (no emission until the
subsequent blank line) and for the promised lone-CR behavior.

In `@packages/bruno-electron/src/ipc/network/sse-event-buffer.spec.js`:
- Around line 33-35: Reformat the sseEventBuffer.push call in the test so its
single Buffer.from argument remains on the same line as the function call,
avoiding newlines inside the function parentheses.
🪄 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 Plus

Run ID: f816a76e-faca-4d70-8fbf-faa9d65aacd9

📥 Commits

Reviewing files that changed from the base of the PR and between 8496be1 and 47fe6ad.

📒 Files selected for processing (3)
  • packages/bruno-electron/src/ipc/network/index.js
  • packages/bruno-electron/src/ipc/network/sse-event-buffer.js
  • packages/bruno-electron/src/ipc/network/sse-event-buffer.spec.js

Comment thread packages/bruno-electron/src/ipc/network/sse-event-buffer.js
Comment thread packages/bruno-electron/src/ipc/network/sse-event-buffer.js
Comment thread packages/bruno-electron/src/ipc/network/sse-event-buffer.spec.js Outdated
@sid-bruno

Copy link
Copy Markdown
Collaborator

@sammaji thanks for the PR, a few sanity cases, can we add additional tests for super slow streams so the request timeout is being respected, for cases where a malformed stream or never ending stream doesn't just keep waiting (this should mostly be handled by axios but a test would help)

@sammaji

sammaji commented Jul 25, 2026

Copy link
Copy Markdown
Author

@sid-bruno from my testing, here's what I found:

For streams, the request timeout is only enforced until the first chunk has arrived. So if I set a timeout that triggers before the first chunk has arrived, I get timeout exceeded. But once first chunk has arrived, timeout is not longer enforced.

never ending stream doesn't just keep waiting

Right now streams never end (even if request timeout is set).

This is how axios handles request timeout, and it makes sense. SSE streams are meant to be long running events, request level timeout should not stop long running streams. If we want to enforce timeout, many applications have a "Stream Idle timeout" which triggers if the stream is idle for said time.

@sid-bruno

Copy link
Copy Markdown
Collaborator

@sammaji Yeah i just need the first one to be tested by the e2e, the idle timer will need a lot more work in the codebase so I'd like to spend some time thinking all impacted areas before working on that.

just the e2e for the first chunk timeout should be good, if you don't have the time, i'll take over the PR as I find time.

@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: 1

🤖 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/sse-event-buffer.spec.js`:
- Around line 107-122: Update the SSE test around the response returned by
makeAxiosInstance().get so response.data is listened to for errors before the
finally block calls close(). Attach a no-op or otherwise handled error listener
to the IncomingMessage stream before cleanup, while preserving the existing
status and content-type assertions.
🪄 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 Plus

Run ID: a89a83fd-75a1-4fbb-8708-58844a70a61f

📥 Commits

Reviewing files that changed from the base of the PR and between 47fe6ad and e6c5efd.

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

Comment thread packages/bruno-electron/src/ipc/network/sse-event-buffer.spec.js

@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

🤖 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/sse-event-buffer.spec.js`:
- Around line 1-142: Add semicolons throughout the new sse-event-buffer.spec.js
test file, including after statements, declarations, function expressions, and
object properties where required by the project’s JavaScript style. Preserve the
existing test behavior and structure.
- Around line 40-45: Add focused tests in the existing sseEventBuffer
normalization suite for lone \r line endings and for a CRLF delimiter split
across two push calls. Assert both produce the same single normalized event
without an extra blank line, reusing createSseEventBuffer and the existing
events expectation style.
🪄 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 Plus

Run ID: 67ef9dbe-d236-405c-8377-a6956fb567f8

📥 Commits

Reviewing files that changed from the base of the PR and between e6c5efd and 3896e82.

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

Comment thread packages/bruno-electron/src/ipc/network/sse-event-buffer.spec.js
Comment thread packages/bruno-electron/src/ipc/network/sse-event-buffer.spec.js Outdated

@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: 1

🤖 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/sse-event-buffer.js`:
- Around line 32-43: Update the SSE event buffer’s event extraction loop to skip
empty slices when consecutive separators produce a blank event, while preserving
valid event dispatch. Update flush to return null for whitespace/newline-only
leftovers, rather than forwarding them as events.
🪄 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 Plus

Run ID: 31029cf4-05e1-4171-85a3-ece8206f40e5

📥 Commits

Reviewing files that changed from the base of the PR and between 3896e82 and 5f247ae.

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

Comment thread packages/bruno-electron/src/ipc/network/sse-event-buffer.js
@sammaji

sammaji commented Jul 29, 2026

Copy link
Copy Markdown
Author

hey @sid-bruno @anusree-bruno have added the test cases and resolved all CRs. can you review once.

the idle timer will need a lot more work in the codebase so I'd like to spend some time thinking all impacted areas before working on that.

agreed, even the ux of the sse response viewer needs a bit of work. right now its just displaying json (minified version). ideally we should show a json editor (if we can detect the object is a json).

let me know if you need a hand 🙇

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.

SSE events in preview are shown by newlines, making them unreadable.

3 participants