-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Server Sent Events #2443
Comments
The bug here is that server sent events needs some special handling |
There is also https://developer.chrome.com/articles/fetch-streaming-requests/ to consider. But because Bun only supports HTTP/1.x right now, it's not as relevant. |
You can use HTTP / 1.1 at this moment until we add support for HTTP / 2 Flush was fixed by #3073 This should work on the next version: function sendSSECustom(controller: ReadableStreamDirectController, eventName: string, data: string) {
return controller.write(`event: ${eventName}\ndata:${JSON.stringify(data)}\n\n`);
}
function sendSSEMessage(controller: ReadableStreamDirectController, data: string) {
return controller.write(`data:${JSON.stringify(data)}\n\n`);
}
function sse(req: Request): Response {
const signal = req.signal;
return new Response(
new ReadableStream({
type: "direct",
async pull(controller: ReadableStreamDirectController) {
while (!signal.aborted) {
await sendSSECustom(controller, "bun", "Hello, World!");
await sendSSEMessage(controller, "Hello, World!");
await controller.flush();
await Bun.sleep(1000);
}
controller.close();
},
}),
{ status: 200, headers: { "Content-Type": "text/event-stream" } },
);
}
Bun.serve({
port: 3000,
fetch(req) {
if (new URL(req.url).pathname === "/stream") {
return sse(req);
}
return new Response("Hello, World!");
},
}); You may will wanna use something like lastEventId to resume reconnections (by sending const lastEventId = req.headers.get("last-event-id") For consuming on the server side we will add support to the client soon. |
This works in Node, and almost in Bun. // send proper headers
response.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive'
})
// send data every second
setInterval(function() {
response.write(`data:foo\n\n`)
}, 1000) With Bun the data is only sent every 5th time or so. Works fine with bigger messages. There must be some kind of flushing issue. |
Have a look at #2663. For me this is working without the flush issue using bun 0.7.0. |
I am on today's canary build and it is working great. |
This issue has been fixed, tested as of Bun v1.0.7.
|
@Electroid @Jarred-Sumner can confirm. SSE works like a charm with v1.0.7! Announceworthy I'd say. Thank you, gentlemen! |
It's working for me too, but how do you fix the TypeScript errors? I'm getting And if I add If I look at the c'tor for |
No docs? That's what the AI on the documentation page says: Bun supports Server-Sent Events (SSE) and you can implement them by using a function sendSSEMessage(controller, data) {
controller.enqueue(`data: ${JSON.stringify(data)}\n\n`);
}
function sse(req) {
const { signal } = req;
return new Response(
new ReadableStream({
start(controller) {
const interval = setInterval(() => {
sendSSEMessage(controller, "Hello, World!");
}, 1000);
signal.onabort = () => {
clearInterval(interval);
controller.close();
};
}
}),
{
status: 200,
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
}
}
);
}
Bun.serve({
fetch(req) {
if (new URL(req.url).pathname === "/sse") {
return sse(req);
}
return new Response("Not Found", { status: 404 });
}
}); This code sets up an SSE endpoint at Remember to adjust the code according to your needs, especially if you want to include event IDs or custom event names. |
@ Not work, I use v 1.1.34 In node express code work (bun dev), but in bun the same code not (bun -b dev), return 204 no content. |
What is the problem this feature would solve?
Implementing Server-Sent Events from Buns HTTP server is seemingly not possible at the moment, as returning a ReadableStream as the data of a Response object sends no response data (headers or body content) until the stream is closed.
What is the feature you are proposing to solve the problem?
Being able to return a ReadableStream object as the data source of a HTTP Response, having headers be instantly sent to the clients, and data be sent to the client as it is enqueued. I imagine the API would look something like this:
This is based off how Deno works, a Deno example can found here: https://dash.deno.com/playground/server-sent-events
What alternatives have you considered?
I think the Deno way best fits Bun as they both use the Web Standard Response object for HTTP Responses. And Bun also already allows returning streams in some cases, such as when using the file API.
However another method could be to implement something specific just for return streams to replicate Nodes
res.write()
method.The text was updated successfully, but these errors were encountered: