Skip to content
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 support #37

Open
vrozaev opened this issue Jun 4, 2024 · 2 comments
Open

WebSockets support #37

vrozaev opened this issue Jun 4, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@vrozaev
Copy link

vrozaev commented Jun 4, 2024

Could you add support of WebSockets please?

I see it as an ability to create a specified route and handler.

@resure resure added the enhancement New feature or request label Jun 4, 2024
@resure
Copy link
Contributor

resure commented Jun 5, 2024

We'll probably add support to expresskit itself later, but in the meanwhile you can try to setup websocket connections on your app's side, just like with ordinary express.js servers.

Basically, you need to:

  1. Register WS server
  2. Receive upgrade request (handle it as a regular GET request: check auth etc.)
  3. Perform upgrade to websocket

Some code samples:

// Entrypoint to application

// ...

const app = new ExpressKit(nodekit, {
    'GET /ws': {
        handler: (req, res) => {
            res.websocket('main', (ws) => {
                req.ctx.log('Client connected');

                ws.send('hey there');

                ws.on('message', (message) => {
                    req.ctx.log('Got message', {message});
                    ws.send('got your message');
                });
            });
        },
    }
});

// Registering ws server
const wss = new WebSocket.Server({noServer: true});

// Handling upgrade request
app.httpServer.on(
    'upgrade',
    (req: http.IncomingMessage, socket: net.Socket, upgradeHead: Buffer) => {
        const res = new http.ServerResponse(req) as Response;
        res.assignSocket(socket);

        const head = Buffer.alloc(upgradeHead.length);
        upgradeHead.copy(head);

        res.websocket = (wssName: string, cb: Function) => {
            wss.handleUpgrade(req, socket, head, (client) => {
                wss.emit('connection', client, req);
                if (cb) {
                    cb(client);
                }
            });
        };

        return this.expressApp(req, res);
    },
);

@vrozaev
Copy link
Author

vrozaev commented Jun 6, 2024

Amazing, I make it work!

One note though: I replaced this.expressApp(req, res); with return app.express(req, res);.

So the working code is:

// Entrypoint to application

// ...

const app = new ExpressKit(nodekit, {
    'GET /ws': {
        handler: (req, res) => {
            res.websocket('main', (ws) => {
                req.ctx.log('Client connected');

                ws.send('hey there');

                ws.on('message', (message) => {
                    req.ctx.log('Got message', {message});
                    ws.send('got your message');
                });
            });
        },
    }
});

// Registering ws server
const wss = new WebSocket.Server({noServer: true});

// Handling upgrade request
app.httpServer.on(
    'upgrade',
    (req: http.IncomingMessage, socket: net.Socket, upgradeHead: Buffer) => {
        const res = new http.ServerResponse(req) as Response;
        res.assignSocket(socket);

        const head = Buffer.alloc(upgradeHead.length);
        upgradeHead.copy(head);

        res.websocket = (wssName: string, cb: Function) => {
            wss.handleUpgrade(req, socket, head, (client) => {
                wss.emit('connection', client, req);
                if (cb) {
                    cb(client);
                }
            });
        };

        return app.express(req, res);
    },
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants