Skip to content

feat: SSEResponse class for streaming Server-Side Events#9931

Open
michalsn wants to merge 4 commits intocodeigniter4:4.8from
michalsn:feat/sse-response
Open

feat: SSEResponse class for streaming Server-Side Events#9931
michalsn wants to merge 4 commits intocodeigniter4:4.8from
michalsn:feat/sse-response

Conversation

@michalsn
Copy link
Member

@michalsn michalsn commented Feb 6, 2026

Description
This PR introduces SSEResponse, a new response class for streaming Server-Sent Events over HTTP. The class provides event(), comment(), and retry() methods for sending SSE fields to the client. Array data passed to event() is automatically JSON-encoded. The response also handles output buffering, session closing, and appropriate header management.

SSEResponse implements the NonBufferedResponseInterface, which is shared with DownloadResponse. Guard checks in CodeIgniter, PageCache, and the Toolbar that previously referenced DownloadResponse directly now rely on this interface instead. This ensures that both download and SSE responses are correctly excluded from page caching, toolbar injection, and body rendering.

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value (without duplication)
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

@michalsn michalsn added new feature PRs for new features 4.8 PRs that target the `4.8` branch. labels Feb 7, 2026
Copy link
Contributor

@datamweb datamweb left a comment

Choose a reason for hiding this comment

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

First of all, I’m really happy to see CodeIgniter continuing its path towards modernization.

I had a couple of thoughts regarding the example provided in the documentation. While the current example is excellent from a PHP developer’s perspective and clearly demonstrates the API usage, I believe it may be less impactful for developers who are focused on building end‑user products.

Perhaps a more product‑oriented example could better showcase the real value of this class — for example, a small notification system or a real‑time update scenario. This could help readers more intuitively grasp the practical power and use cases enabled by this addition.

*
* Each line becomes "{prefix}: {line}\n", terminated by an extra "\n".
*/
private function formatMultiline(string $prefix, string $value): string
Copy link
Contributor

Choose a reason for hiding this comment

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

formatMultiline() and write() appear to be natural extension
boundaries (I/O and formatting).
Would making them protected help avoid duplication or framework
forking when custom SSE behavior is needed?

Suggested change
private function formatMultiline(string $prefix, string $value): string
protected function formatMultiline(string $prefix, string $value): string

Copy link
Member Author

Choose a reason for hiding this comment

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

Formatting methods are dictated by the spec, not by application needs. I don't see a scenario where this would need modification.

/**
* Write raw SSE output and flush.
*/
private function write(string $output): bool
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
private function write(string $output): bool
protected function write(string $output): bool

Copy link
Member Author

Choose a reason for hiding this comment

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

Again, I can't imagine a legitimate scenario where this may be handy. If a concrete need comes up later, promoting private to protected is a non-breaking change. Going the other direction isn't.

Co-authored-by: Pooya Parsa <pooya_parsa_dadashi@yahoo.com>
@michalsn
Copy link
Member Author

michalsn commented Feb 7, 2026

@datamweb Thanks for the feedback. I've added a "live notifications" example to better illustrate the idea behind SSE.

Copy link
Contributor

@datamweb datamweb left a comment

Choose a reason for hiding this comment

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

Thank you for addressing this so thoroughly.
Let's see what others say!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.8 PRs that target the `4.8` branch. new feature PRs for new features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants