-
-
Notifications
You must be signed in to change notification settings - Fork 639
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
WebSockets #1153
Comments
Not just cloudflare, but also Node.js and deno |
You can use WebSockets with the current version of Hono on Deno. Refer: https://github.com/orgs/honojs/discussions/755 It can also be supported on Cloudflare Workers. More info: https://developers.cloudflare.com/workers/learning/using-websockets/ Supporting more WebSocket features is outside the scope of Hono. For Node.js, you can't use WebSockets with the current Node.js Adapter and there are no plans to implement it. But, if you want this feature, you might be able to write the PR yourself. |
Is there an example with Hono and CloudFlare workers too? I looked into the documentation of CloudFlare, but couldn't get it working with Hono. |
Hi @JustJoostNL ! I've written an example. Try this! // websocket.ts
import type { WebSocket as CFWebSocket } from '@cloudflare/workers-types'
import { Hono } from 'hono'
import { html } from 'hono/html'
const app = new Hono()
app.get('/', (c) => {
return c.html(
html`<html>
<body>
<script>
const hostname = window.location.host
const protocol = document.location.protocol === 'http:' ? 'ws://' : 'wss://'
const ws = new WebSocket(protocol + hostname + '/websocket')
ws.addEventListener('message', ({ data }) => {
console.log(data)
})
</script>
<h1>WebSocket</h1>
</body>
</html>`
)
})
app.get('/websocket', (c) => {
const upgradeHeader = c.req.header('Upgrade')
if (upgradeHeader !== 'websocket') {
return c.text('Expected websocket', 400)
}
const webSocketPair = new WebSocketPair()
const client = webSocketPair[0]
const server = webSocketPair[1] as unknown as CFWebSocket
server.accept()
server.send('Hello')
return new Response(null, {
status: 101,
webSocket: client,
})
})
export default app
|
Thanks! |
It should be fairly trivial to make universal middleware for Workers, Deno and possibly Node. If I have the time, I could look into it as 3rd party middleware but no promise. Bun seems to be out of the question because of how their API works. |
Yeah, making a "universal" middleware is make sense. |
Is there currently any restriction on manually implementing the connection upgrade on the route handler? |
You have to use the node adapter with the |
WebSockets example for Node.js, it's way simpler than what I described import { serve } from "@hono/node-server";
import { Hono } from "hono";
import { WebSocketServer } from 'ws';
const app = new Hono();
const server = serve(app, (info) => {
console.log(`Listening on http://localhost:${info.port}`);
});
const wss = new WebSocketServer({ server });
wss.on("connection", function connection(ws) {
ws.on("error", console.error);
ws.on("message", function message(data) {
console.log("received: %s", data);
});
ws.send("something");
}); |
Awesome this is exactly what I needed thank you 🎉 |
I couldn't find any documentation on the WebSocket server included with Bun. This is how I got it working, but I'm sure there's a better way to handle upgrades. import { Hono } from 'hono'
const app = new Hono()
Bun.serve({
fetch: (req, server) => {
if (server.upgrade(req)) {
// handle authentication
}
return app.fetch(req, server)
},
websocket: {
message(ws, message) {},
open(ws) {
ws.send('Hello!')
},
close(ws, code, message) {},
drain(ws) {}
},
port: 8080
}) |
For someone interested in using WebSockets via node server and socket.io check out this snippet import { serve } from "@hono/node-server";
import { Hono } from "hono";
import type { Server as HTTPSServer } from "node:http";
import { Server as SocketIOServer } from "socket.io";
const app = new Hono();
app.get("/", (c) => c.text("Hello Hono!"));
const server = serve(
{
fetch: app.fetch,
port: 5000,
},
(add) => {
console.log('Listening on http://localhost:'+${add.port});
}
);
const io = new SocketIOServer(server as HTTPSServer);
io.on("connection", (socket) => {
socket.emit("hello", "world");
socket.on("hello", (data) => {
socket.broadcast.emit("hello", data);
});
}); |
I would love to see a simpler way to handle
|
Another example how to upgrade all WebSocket upgrade requests using Bun.serve({
port: process.env.PORT || 3000,
fetch: (req, server) => {
// check if request is websocket
if (req.headers.get('upgrade') === 'websocket') {
const success = server.upgrade(req);
if (success) {
// Bun automatically returns a 101 Switching Protocols
// if the upgrade succeeds
return undefined;
}
}
// handle HTTP request normally
return app.fetch(req, server)
},
websocket: webSocketHandler,
}) |
This worked in bun with typescript? That's undefined on |
I'm using JavaScript. You could try the other method i mentioned (inside the |
Ah I understand why, for the typescript folks, you can do this:
was unaware of |
Nice you found out! I did a |
It's because when you do the shortcut of This is the type for fetch: (request: Request, Env?: E['Bindings'] | {}, executionCtx?: ExecutionContext) => Response | Promise<Response>; |
I don't think it's possible to handle upgrades inside the route handler itself in Bun, but it's very doable in Node. I've made a PR to address this a while ago but I didn't have much time to update it so it's stale for now. |
I really like how this is done in Elysia |
Elysia has the advantage of supporting only Bun in this case because implementing a ws handler function would require some different code for every runtime. My plan was to make a helper like this without Bun support but I've yet to PR anything. import { upgradeWebSocket } from "hono/ws";
import { Hono } from "hono";
const app = new Hono();
app.get("/ws", (c) => upgradeWebSocket(c, (ws) => {})); |
I see. Hono has to do more work to support multiple runtimes. Maybe Elysia is a better if only building for Bun. |
If you want to have "normal" websockets (with listeners) in Bun/hono I made this little bit of code: https://gist.github.com/tobowers/2117365c8210d1758a4c6e2f859619c0 |
That's pretty nice! |
I'd rather have the 7x performance by Bun :) |
Sure, but most libraries can't handle it. |
What libraries are you referring to? (I only need a simple web framework / library which can handle routes and WebSocket but is preferably "cross-runtime" and works with Bun) |
I mean libraries consuming websockets |
Not aware of any such libraries. Just need a standard WebSocket API |
Now, we have WebSocket Helper / Adapter! #2265 |
May I ask how to use I don't know how to implement similar functions in hono. I implemented it in Express like this: // server.ts
import express from 'express'
import http from 'http'
const app = express()
const server = http.createServer(app)
const io = new Server(server, {
cors: {
origin: '*',
},
})
io.on('connection', (socket) => {
console.log('a user connected')
})
app.set('io', io)
app.use('/messages', authenticate, messageRouter) // messages.ts
import express from 'express'
const router = express.Router()
router.get('/', (
req: express.Request,
res: express.Response,
) => {
const io = req.app.get('io')
io.emit('message', 'hello1')
// ...
}) |
Please implement WebSockets feature in honojs.
https://developers.cloudflare.com/workers/runtime-apis/websockets/
The text was updated successfully, but these errors were encountered: