test bun stream sse and http-stream

This commit is contained in:
2026-02-01 01:26:57 +08:00
parent fed87eb3a1
commit b081a03399
4 changed files with 71 additions and 8 deletions

38
demo/bun/src/index.ts Normal file
View File

@@ -0,0 +1,38 @@
const server = Bun.serve({
port: 5002,
fetch(request: Bun.BunRequest, server) {
const url = new URL(request.url);
if (url.pathname === '/stream') {
// 直接使用 Bun 的原生 ReadableStream
const readable = new ReadableStream({
async start(controller) {
for (let i = 1; i <= 10; i++) {
// 检查客户端是否断开
if (request.signal.aborted) {
console.log('客户端已断开');
controller.close();
return;
}
controller.enqueue(`${new Date().toISOString()}${i} 批数据\n`);
await new Promise(r => setTimeout(r, 100)); // 模拟延迟
}
controller.close();
}
});
request.signal.addEventListener('abort', () => {
console.log('Request aborted by client');
});
return new Response(readable, {
status: 200,
headers: {
'Content-Type': 'text/plain',
'Transfer-Encoding': 'chunked'
}
});
}
return new Response('Not Found', { status: 404 });
}
});

View File

@@ -1,7 +1,7 @@
{ {
"$schema": "https://json.schemastore.org/package", "$schema": "https://json.schemastore.org/package",
"name": "@kevisual/router", "name": "@kevisual/router",
"version": "0.0.65", "version": "0.0.66",
"description": "", "description": "",
"type": "module", "type": "module",
"main": "./dist/router.js", "main": "./dist/router.js",

View File

@@ -50,7 +50,7 @@ export class BunServer extends ServerBase implements ServerType {
port, port,
hostname, hostname,
idleTimeout: 0, // 4 minutes idle timeout (max 255 seconds) idleTimeout: 0, // 4 minutes idle timeout (max 255 seconds)
fetch: async (request: Bun.BunRequest, server: any) => { fetch: async (request: Bun.BunRequest, server: Bun.Server<{}>) => {
const host = request.headers.get('host') || 'localhost'; const host = request.headers.get('host') || 'localhost';
const clientInfo = server.requestIP(request); // 返回 { address: string, port: number } 或 null const clientInfo = server.requestIP(request); // 返回 { address: string, port: number } 或 null
const url = new URL(request.url, `http://${host}`); const url = new URL(request.url, `http://${host}`);
@@ -72,6 +72,7 @@ export class BunServer extends ServerBase implements ServerType {
// 将 Bun 的 Request 转换为 Node.js 风格的 req/res // 将 Bun 的 Request 转换为 Node.js 风格的 req/res
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
const reqListener: { event: string; listener: Function }[] = [];
const req: RouterReq = { const req: RouterReq = {
url: url.pathname + url.search, url: url.pathname + url.search,
method: request.method, method: request.method,
@@ -81,12 +82,29 @@ export class BunServer extends ServerBase implements ServerType {
remoteAddress: request?.remoteAddress || request?.ip || clientInfo?.address || '', remoteAddress: request?.remoteAddress || request?.ip || clientInfo?.address || '',
remotePort: clientInfo?.port || 0, remotePort: clientInfo?.port || 0,
}, },
// @ts-ignore on: (event: string, listener: Function) => {
reqListener.push({ event, listener });
},
bun: { bun: {
request, // 原始请求对象 request, // 原始请求对象
server, // 原始服务器对象 server, // 原始服务器对象
resolve
} }
}; };
const onClose = () => {
reqListener.forEach(item => {
if (item.event === 'close') {
item.listener();
}
});
reqListener.length = 0;
}
// 监听请求的取消事件
if (request.signal) {
request.signal.addEventListener('abort', () => {
onClose();
});
}
const res: RouterRes = { const res: RouterRes = {
statusCode: 200, statusCode: 200,
@@ -143,7 +161,7 @@ export class BunServer extends ServerBase implements ServerType {
if (callback) callback(); if (callback) callback();
return true; return true;
}, },
pipe(stream: any) { pipe(stream: ReadableStream | NodeJS.ReadableStream) {
this.writableEnded = true; this.writableEnded = true;
// 如果是 ReadableStream直接使用 // 如果是 ReadableStream直接使用
@@ -164,6 +182,7 @@ export class BunServer extends ServerBase implements ServerType {
controller.enqueue(chunk); controller.enqueue(chunk);
}); });
stream.on('end', () => { stream.on('end', () => {
onClose();
controller.close(); controller.close();
}); });
stream.on('error', (err: any) => { stream.on('error', (err: any) => {
@@ -171,9 +190,9 @@ export class BunServer extends ServerBase implements ServerType {
}); });
}, },
cancel() { cancel() {
if (stream.destroy) { // 只有NODE流才有destroy方法
stream.destroy(); // @ts-ignore
} stream?.destroy?.();
} }
}); });

View File

@@ -104,6 +104,12 @@ export type RouterReq<T = {}> = {
}; };
body?: string; body?: string;
cookies?: Record<string, string>; cookies?: Record<string, string>;
bun?: {
request: Bun.BunRequest;
server: Bun.Server<{}>;
resolve: (response: Response) => void;
}
on: (event: 'close', listener: Function) => void;
} & T; } & T;
export type RouterRes<T = {}> = { export type RouterRes<T = {}> = {
@@ -116,6 +122,6 @@ export type RouterRes<T = {}> = {
setHeader: (name: string, value: string | string[]) => void; setHeader: (name: string, value: string | string[]) => void;
cookie: (name: string, value: string, options?: any) => void; cookie: (name: string, value: string, options?: any) => void;
write: (chunk: any) => void; write: (chunk: any) => void;
pipe: (stream: any) => void; pipe: (stream: ReadableStream) => void;
end: (data?: any) => void; end: (data?: any) => void;
} & T; } & T;