Thursday, February 3, 2022

[SOLVED] Typescript error for "app.ws" using express-ws

Issue

In my small project, I want to build a BabyCam that can be accessed from any web browser using a Raspberry Pi Zero. For this, I would like to open a web socket using express-is to stream video to several clients. I am basing most of the video-related code on the raspivid-stream module. However, when trying to access the web socket, I get a type error for app.ws(... stating Property 'ws' does not exist on type 'Application'. Of course, I imported both the typings for express and express-ws.

I am not really sure, what the problem is as the same call in JavaScript appears work fine. Here's the code - I am glad for any help!

import express from 'express';
import { Request, Response } from 'express';
import fs from 'fs';
import https from 'https';
import http from 'http';
import raspividStream from 'raspivid-stream';
import expressWs from 'express-ws';


const server: express.Application = express();

const httpPort: number = 8080;
const httpsPort: number = 8443;

const sslCredentials = {
    key: fs.readFileSync('../ssl/localhost.key', 'utf8'),
    cert: fs.readFileSync('../ssl/localhost.cert', 'utf8')
};

// CREATE SERVER

const httpServer = http.createServer(server);
const httpsServer = https.createServer(sslCredentials, server);

expressWs(server, httpsServer);

// ROUTES

server.get('*', (req: Request, res:Response) => {
    if (!req.secure) {
        return res.redirect(`https://${req.hostname}:${httpsPort}${req.originalUrl}`);
    }
    res.sendFile(__dirname + '/client/index.html');
});

// WEBSOCKET

server.ws('/video-stream', (ws) => {
    console.log('Client connected');


    ws.send(JSON.stringify({
    action: 'init',
    width: '960',
    height: '540'
    }));

    var videoStream = raspividStream({ rotation: 180 });

    videoStream.on('data', (data) => {
        ws.send(data, { binary: true }, (error) => { if (error) console.error(error); });
    });

    ws.on('close', () => {
        console.log('Client left');
        videoStream.removeAllListeners('data');
    });
});


// START SERVER

httpServer.listen(httpPort, () => {
    console.log(`BabyCam (redirect) listening at http://localhost:${httpPort}/`);
}); 

httpsServer.listen(httpsPort, () => {
    console.log(`BabyCam (SSL) listening at https://localhost:${httpsPort}/`);
});

Solution

Express.Application does not have a member called ws. That's the error you get. You need to use the return value of expressWS(server, httpsServer). The app you can access there is typed as Express.Application & WithWebsocketMethod.



Answered By - Stramski
Answer Checked By - Timothy Miller (WPSolving Admin)