Bun WebSocket Server by secondsky/claude-skills
npx skills add https://github.com/secondsky/claude-skills --skill 'Bun WebSocket Server'Bun 内置了与 Bun.serve() 集成的 WebSocket 支持。
const server = Bun.serve({
fetch(req, server) {
// 升级到 WebSocket
if (server.upgrade(req)) {
return; // 升级成功
}
return new Response("Not a WebSocket request", { status: 400 });
},
websocket: {
open(ws) {
console.log("Client connected");
},
message(ws, message) {
console.log("Received:", message);
ws.send(`Echo: ${message}`);
},
close(ws) {
console.log("Client disconnected");
},
},
});
console.log(`WebSocket server running on ws://localhost:${server.port}`);
Bun.serve({
fetch(req, server) {
server.upgrade(req);
},
websocket: {
// 客户端连接
open(ws) {
console.log("New connection");
},
// 收到消息
message(ws, message) {
// message 是 string | Buffer
if (typeof message === "string") {
console.log("Text:", message);
} else {
console.log("Binary:", message);
}
},
// 连接关闭
close(ws, code, reason) {
console.log(`Closed: ${code} - ${reason}`);
},
// 排空事件(缓冲区已刷新)
drain(ws) {
console.log("Buffer drained");
},
// 收到 Ping
ping(ws, data) {
// 自动发送 Pong
},
// 收到 Pong
pong(ws, data) {
console.log("Pong received");
},
},
});
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
websocket: {
message(ws, message) {
// 发送文本
ws.send("Hello");
// 发送 JSON
ws.send(JSON.stringify({ type: "greeting", data: "Hello" }));
// 发送二进制数据
ws.send(new Uint8Array([1, 2, 3]));
ws.send(Buffer.from("binary data"));
// 使用压缩发送
ws.send("compressed message", true);
// 检查缓冲区是否已满
const bufferedAmount = ws.send("data");
if (bufferedAmount > 1024 * 1024) {
console.log("Buffer getting full");
}
},
}
interface UserData {
id: string;
name: string;
joinedAt: Date;
}
Bun.serve<UserData>({
fetch(req, server) {
const url = new URL(req.url);
const userId = url.searchParams.get("userId");
// 在升级期间附加数据
server.upgrade(req, {
data: {
id: userId,
name: "User " + userId,
joinedAt: new Date(),
},
});
},
websocket: {
open(ws) {
// 访问附加的数据
console.log(`${ws.data.name} connected`);
},
message(ws, message) {
console.log(`${ws.data.name}: ${message}`);
},
},
});
Bun.serve({
fetch(req, server) {
const url = new URL(req.url);
const room = url.searchParams.get("room") || "general";
server.upgrade(req, {
data: { room },
});
},
websocket: {
open(ws) {
// 订阅主题
ws.subscribe(ws.data.room);
// 向主题发布消息(排除发送者)
ws.publish(ws.data.room, `User joined ${ws.data.room}`);
},
message(ws, message) {
// 向房间内所有成员广播(排除发送者)
ws.publish(ws.data.room, message);
},
close(ws) {
// 取消订阅(关闭时自动执行)
ws.unsubscribe(ws.data.room);
ws.publish(ws.data.room, "User left");
},
},
});
Bun.serve({
fetch(req, server) {
server.upgrade(req);
},
websocket: {
open(ws) {
// 订阅全局主题
ws.subscribe("global");
},
message(ws, message) {
// 向所有客户端广播(包括发送者)
server.publish("global", message);
},
},
});
const server = Bun.serve({
fetch(req, server) {
const url = new URL(req.url);
// HTTP 端点用于发布
if (url.pathname === "/broadcast") {
const message = url.searchParams.get("msg");
server.publish("global", message);
return new Response("Broadcasted");
}
server.upgrade(req);
},
websocket: {
open(ws) {
ws.subscribe("global");
},
},
});
// 也可以从 fetch 外部发布
setInterval(() => {
server.publish("global", `Server time: ${new Date().toISOString()}`);
}, 5000);
Bun.serve({
websocket: {
// 最大消息大小(默认 16MB)
maxPayloadLength: 1024 * 1024, // 1MB
// 空闲超时(秒)(默认 120)
idleTimeout: 60,
// 背压限制
backpressureLimit: 1024 * 1024,
// 启用压缩
perMessageDeflate: true,
// 或使用选项
perMessageDeflate: {
compress: "shared",
decompress: "shared",
},
// 发送/接收 ping
sendPings: true,
// 处理器
open(ws) {},
message(ws, message) {},
close(ws) {},
},
});
// 浏览器
const ws = new WebSocket("ws://localhost:3000");
ws.onopen = () => {
ws.send("Hello Server!");
};
ws.onmessage = (event) => {
console.log("Received:", event.data);
};
ws.onclose = () => {
console.log("Disconnected");
};
Bun.serve({
fetch(req, server) {
// 升级前验证身份
const token = req.headers.get("Authorization");
if (!verifyToken(token)) {
return new Response("Unauthorized", { status: 401 });
}
const user = decodeToken(token);
server.upgrade(req, {
data: { userId: user.id },
});
},
websocket: {
open(ws) {
console.log(`Authenticated user ${ws.data.userId} connected`);
},
},
});
| 错误 | 原因 | 解决方法 |
|---|---|---|
Upgrade failed | 无效请求 | 检查升级头信息 |
Connection closed | 客户端断开连接 | 在 close 处理器中处理 |
Message too large | 超过 maxPayloadLength | 增加限制或分块数据 |
Backpressure | 客户端响应慢 | 检查缓冲区,等待 drain 事件 |
Bun.serve({
fetch(req, server) {
const url = new URL(req.url);
const username = url.searchParams.get("user") || "Anonymous";
server.upgrade(req, {
data: { username },
});
},
websocket: {
open(ws) {
ws.subscribe("chat");
ws.publish("chat", `${ws.data.username} joined`);
},
message(ws, message) {
ws.publish("chat", `${ws.data.username}: ${message}`);
},
close(ws) {
ws.publish("chat", `${ws.data.username} left`);
},
},
});
在以下情况下加载 references/compression.md:
在以下情况下加载 references/scaling.md:
每周安装次数
–
代码仓库
GitHub 星标数
90
首次出现
–
安全审计
Bun has built-in WebSocket support integrated with Bun.serve().
const server = Bun.serve({
fetch(req, server) {
// Upgrade to WebSocket
if (server.upgrade(req)) {
return; // Upgraded successfully
}
return new Response("Not a WebSocket request", { status: 400 });
},
websocket: {
open(ws) {
console.log("Client connected");
},
message(ws, message) {
console.log("Received:", message);
ws.send(`Echo: ${message}`);
},
close(ws) {
console.log("Client disconnected");
},
},
});
console.log(`WebSocket server running on ws://localhost:${server.port}`);
Bun.serve({
fetch(req, server) {
server.upgrade(req);
},
websocket: {
// Client connected
open(ws) {
console.log("New connection");
},
// Message received
message(ws, message) {
// message is string | Buffer
if (typeof message === "string") {
console.log("Text:", message);
} else {
console.log("Binary:", message);
}
},
// Connection closed
close(ws, code, reason) {
console.log(`Closed: ${code} - ${reason}`);
},
// Drain event (buffer flushed)
drain(ws) {
console.log("Buffer drained");
},
// Ping received
ping(ws, data) {
// Pong sent automatically
},
// Pong received
pong(ws, data) {
console.log("Pong received");
},
},
});
websocket: {
message(ws, message) {
// Send text
ws.send("Hello");
// Send JSON
ws.send(JSON.stringify({ type: "greeting", data: "Hello" }));
// Send binary
ws.send(new Uint8Array([1, 2, 3]));
ws.send(Buffer.from("binary data"));
// Send with compression
ws.send("compressed message", true);
// Check if buffer is full
const bufferedAmount = ws.send("data");
if (bufferedAmount > 1024 * 1024) {
console.log("Buffer getting full");
}
},
}
interface UserData {
id: string;
name: string;
joinedAt: Date;
}
Bun.serve<UserData>({
fetch(req, server) {
const url = new URL(req.url);
const userId = url.searchParams.get("userId");
// Attach data during upgrade
server.upgrade(req, {
data: {
id: userId,
name: "User " + userId,
joinedAt: new Date(),
},
});
},
websocket: {
open(ws) {
// Access attached data
console.log(`${ws.data.name} connected`);
},
message(ws, message) {
console.log(`${ws.data.name}: ${message}`);
},
},
});
Bun.serve({
fetch(req, server) {
const url = new URL(req.url);
const room = url.searchParams.get("room") || "general";
server.upgrade(req, {
data: { room },
});
},
websocket: {
open(ws) {
// Subscribe to a topic
ws.subscribe(ws.data.room);
// Publish to topic (excludes sender)
ws.publish(ws.data.room, `User joined ${ws.data.room}`);
},
message(ws, message) {
// Broadcast to all in room (excludes sender)
ws.publish(ws.data.room, message);
},
close(ws) {
// Unsubscribe (automatic on close)
ws.unsubscribe(ws.data.room);
ws.publish(ws.data.room, "User left");
},
},
});
Bun.serve({
fetch(req, server) {
server.upgrade(req);
},
websocket: {
open(ws) {
// Subscribe to global topic
ws.subscribe("global");
},
message(ws, message) {
// Broadcast to ALL clients including sender
server.publish("global", message);
},
},
});
const server = Bun.serve({
fetch(req, server) {
const url = new URL(req.url);
// HTTP endpoint to publish
if (url.pathname === "/broadcast") {
const message = url.searchParams.get("msg");
server.publish("global", message);
return new Response("Broadcasted");
}
server.upgrade(req);
},
websocket: {
open(ws) {
ws.subscribe("global");
},
},
});
// Can also publish from outside fetch
setInterval(() => {
server.publish("global", `Server time: ${new Date().toISOString()}`);
}, 5000);
Bun.serve({
websocket: {
// Max message size (default 16MB)
maxPayloadLength: 1024 * 1024, // 1MB
// Idle timeout in seconds (default 120)
idleTimeout: 60,
// Backpressure limit
backpressureLimit: 1024 * 1024,
// Enable compression
perMessageDeflate: true,
// Or with options
perMessageDeflate: {
compress: "shared",
decompress: "shared",
},
// Send/receive pings
sendPings: true,
// Handlers
open(ws) {},
message(ws, message) {},
close(ws) {},
},
});
// Browser
const ws = new WebSocket("ws://localhost:3000");
ws.onopen = () => {
ws.send("Hello Server!");
};
ws.onmessage = (event) => {
console.log("Received:", event.data);
};
ws.onclose = () => {
console.log("Disconnected");
};
Bun.serve({
fetch(req, server) {
// Verify auth before upgrade
const token = req.headers.get("Authorization");
if (!verifyToken(token)) {
return new Response("Unauthorized", { status: 401 });
}
const user = decodeToken(token);
server.upgrade(req, {
data: { userId: user.id },
});
},
websocket: {
open(ws) {
console.log(`Authenticated user ${ws.data.userId} connected`);
},
},
});
| Error | Cause | Fix |
|---|---|---|
Upgrade failed | Invalid request | Check upgrade headers |
Connection closed | Client disconnect | Handle in close handler |
Message too large | Exceeds maxPayloadLength | Increase limit or chunk data |
Backpressure | Slow client | Check buffer, wait for drain |
Bun.serve({
fetch(req, server) {
const url = new URL(req.url);
const username = url.searchParams.get("user") || "Anonymous";
server.upgrade(req, {
data: { username },
});
},
websocket: {
open(ws) {
ws.subscribe("chat");
ws.publish("chat", `${ws.data.username} joined`);
},
message(ws, message) {
ws.publish("chat", `${ws.data.username}: ${message}`);
},
close(ws) {
ws.publish("chat", `${ws.data.username} left`);
},
},
});
Load references/compression.md when:
Load references/scaling.md when:
Weekly Installs
–
Repository
GitHub Stars
90
First Seen
–
Security Audits
Office MCP 服务器:39种PDF/Excel/Word/PPT文档处理工具,支持OCR和批量转换
824 周安装
LaTeX中文学位论文助手 | 自动检查格式、GB/T 7714标准、编译与表达优化
594 周安装
多智能体结构化设计评审 - 智能体协作头脑风暴与设计验证流程
584 周安装
fal.ai AI图像编辑工具:风格迁移、对象移除、背景更换一键处理
586 周安装
产品需求文档生成器 | AI产品负责人Sarah | PRD质量评分与迭代优化工具
592 周安装
SQLAlchemy ORM 教程:Python 数据库 ORM 框架与 SQL 查询构建器使用指南
593 周安装
AI智能体电子邮件收件箱搭建指南:使用Resend Webhook实现安全实时邮件处理
625 周安装