How to implement a react js websocket client? - node.js

I want to create a react js application as a web-socket client, In which react js will request a server which I'm already created in node js and working on port no 1234.
I'm beginner to react js. In my application react js client is not requesting to node js server. what I'm missing in following code?
Node_js Server-
var server = require('websocket').server, http = require('http');
require('events').EventEmitter.prototype._maxListeners = 100;
nconf = require('nconf');
var socket = null;
var connection = null;
var filePath = ''
var timeInteval = 0
var LineByLineReader;
var sleep = require('sleep');
function init(){
nconf.argv().env().file({file: 'config.json'});
filePath = nconf.get('file-path');
timeInteval = nconf.get('time-inteval');
}
var main = function () {
init();
socket = new server({
httpServer: http.createServer().listen(1234)
});
console.log('Waiting for Client... On Port No : 1234');
socket.on('request', function (request) {
connection = request.accept(null, request.origin);
var connections = []
connections.push(connection);
console.log(connection.remoteAddress + '=====>>> Connection accepted.');
var lineReader = require('line-reader');
lineReader.eachLine(filePath, function(line, last) {
for (var i = 0; i < connections.length; i++) {
connections[i].sendUTF(line);
}
sleep.sleep(timeInteval)
});
connection.on('message', function (message) {
});
connection.on('close', function (connection) {
console.log('=====>>> Connection closed');
var index = connections.indexOf(connection);
connections.splice(index, 1);
});
connection.on('error', function (connection) {
console.log(connection.remoteAddress + ' : error');
});
});
}
if (require.main === module) {
main();
}
This node js server is working fine for any number of clients.
App.jsx -
var React = require('react')
var ws = require('ws');
var ReactDOM = require('react-dom');
const Echo = React.createClass({
getInitialState(){
return { messages : [] }
},
componentDidMount: function() {
var wsc = new ws('ws://localhost:1234');
wsc.onmessage = function(message) {
this.setState({ messages: message.data });
}.bind(this);
},
render: function() {
return ( this.state.messages );
}
});
const component = ReactDOM.render(
<Echo />,
document.getElementById('container')
);
index.html-
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<title>React App</title>
</head>
<body>
<div id="container">
</div>
<script src = "index.js"></script>
</body>
</html>
webpack.config.js-
var config = {
entry: './App.jsx',
output: {
path:'./',
filename: 'index.js',
},
devServer: {
inline: true,
port: 8090
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'react']
}
}
]
}
}
module.exports = config;

Related

socket.io insufficient resources - react js and node

I'm experimenting a bit with socket.io to create a chat app in real time.
Everything seems to work fine but after a few second socket.io gives me this error:
"websocket.js:50 WebSocket connection to 'ws://localhost:5000/socket.io/?EIO=4&transport=websocket&sid=gbx90aAo73oDoP86AAVP' failed: Insufficient resources"
What am I doing wrong?
Client
import React from "react";
import { useState, useEffect } from "react";
import { io } from "socket.io-client";
const App = () => {
const [conv, setConv] = useState([]);
const [input, setInput] = useState({
sender: "user",
text: "",
});
const socket = io("http://localhost:5000");
const handleChange = (e) => {
setInput({
sender: "user",
text: e.target.value,
});
};
const handleSubmit = (e) => {
e.preventDefault();
socket.emit("input", input);
};
useEffect(() => {
socket.on("output", (data) => {
setConv(data[0].messages);
});
}, [conv]);
return (
<div className="App">
<form onSubmit={handleSubmit}>
<h1>chat</h1>
<div id="messages">
{conv.map((msg, index) => (
<div key={index}>
<p>
{msg.sender}: {msg.text}
</p>
</div>
))}
</div>
<input onChange={handleChange} type="text" />
<input type="submit" />
</form>
</div>
);
};
export default App;
Server
const express = require("express");
const socketIo = require("socket.io");
const http = require("http");
const PORT = 5000;
const app = express();
const server = http.createServer(app);
const io = socketIo(server, {
cors: {
origin: "http://localhost:3000",
},
}); //in case server and client run on different urls
const MongoClient = require("mongodb").MongoClient;
MongoClient.connect("mongodb://localhost:27017", (err, db) => {
if (err) throw err;
console.log("connected");
const database = db.db("local");
const chat = database.collection("chat");
//connect to socket .io
io.on("connection", (socket) => {
// get chat from collection
chat.find().toArray((err, res) => {
if (err) throw err;
// emit the messages
socket.emit("output", res);
});
//handle input events
socket.on("input", (input) => {
let sender = input.sender;
let receiver = "bot";
let text = input.text;
// check if inside chat collection the members array contains the sender and receiver
chat.find({ members: { $all: [sender, receiver] } }).toArray((err, res) => {
if (err) throw err;
let senderInDb = res[0].members[0];
let receiverInDb = res[0].members[1];
//if yes then push the message to the messages array
if (sender === senderInDb && receiver === receiverInDb) {
chat.updateOne(
{ members: { $all: [sender, receiver] } },
{ $push: { messages: { sender: sender, text: text } } }
);
}
});
});
});
});
server.listen(PORT, (err) => {
if (err) console.log(err);
console.log("Server running on Port ", PORT);
});

How to record mic from client then send to server

I would like to record microphone input from the client and then when he stops, send the data to the server and then output the recorded audio to a specific folder.
So far I have for the recording on the client I have followed this
mediaRecorder.onstop = function(e) {
console.log("recorder stopped");
const blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
chunks = [];
const formData = new FormData();
formData.append('audio-file', blob);
return fetch('http://localhost:3000/notes', {
method: 'POST',
body: formData
});
}
console.log(blob) on the client returns an object
Blob { size: 35412, type: "audio/ogg; codecs=opus" }
On the server side I use Node.js
app.post("/notes",function(req,res){
console.log(req);
});
The server receives formData but the body is empty {}
I have also tried XMLHttpRequest with the same result.
I've played about with this type of project before. I created a simple form that allows you to record from the microphone, then upload to the server.
Sound files will be saved in ./sound_files
Just run the node server like
node server.js
And go to localhost:3000 to view the page.
Node code (server.js)
const express = require('express');
const multer = require('multer');
const storage = multer.diskStorage(
{
destination: './sound_files/',
filename: function (req, file, cb ) {
cb( null, file.originalname);
}
}
);
const upload = multer( { storage: storage } );
const app = express();
const port = 3000;
app.use(express.static('./'));
app.post("/notes", upload.single("audio_data"), function(req,res){
res.status(200).send("ok");
});
app.listen(port, () => {
console.log(`Express server listening on port: ${port}...`);
});
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Speech to text test</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="https://bootswatch.com/4/cerulean/bootstrap.min.css">
</head>
<body style="padding:50px;">
<h1>Speech to text test</h1>
<div id="controls">
<button id="recordButton">Record</button>
<button id="transcribeButton" disabled>Stop and upload to server</button>
</div>
<div id="output"></div>
<script src="https://cdn.rawgit.com/mattdiamond/Recorderjs/08e7abd9/dist/recorder.js"></script>
<script>
let rec = null;
let audioStream = null;
const recordButton = document.getElementById("recordButton");
const transcribeButton = document.getElementById("transcribeButton");
recordButton.addEventListener("click", startRecording);
transcribeButton.addEventListener("click", transcribeText);
function startRecording() {
let constraints = { audio: true, video:false }
recordButton.disabled = true;
transcribeButton.disabled = false;
navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
const audioContext = new window.AudioContext();
audioStream = stream;
const input = audioContext.createMediaStreamSource(stream);
rec = new Recorder(input, { numChannels: 1 })
rec.record()
document.getElementById("output").innerHTML = "Recording started..."
}).catch(function(err) {
recordButton.disabled = false;
transcribeButton.disabled = true;
});
}
function transcribeText() {
document.getElementById("output").innerHTML = "Converting audio to text..."
transcribeButton.disabled = true;
recordButton.disabled = false;
rec.stop();
audioStream.getAudioTracks()[0].stop();
rec.exportWAV(uploadSoundData);
}
function uploadSoundData(blob) {
const filename = "sound-file-" + new Date().getTime() + ".wav";
const formData = new FormData();
formData.append("audio_data", blob, filename);
fetch('http://localhost:3000/notes', {
method: 'POST',
body: formData
}).then(async result => {
document.getElementById("output").innerHTML = await result.text();
}).catch(error => {
document.getElementById("output").innerHTML = "An error occurred: " + error;
})
}
</script>
</body>
</html>

Upload Recorded Screen Via Socket.io Not Working

i'm trying to make a zoom/google meet clone.. and i'm using RecordRTC to record the screen and then send it the Node Server via socket.io ...sometimes i get data , and sometimes i don't,..
however i tried to do the same code with websocket ... i didn't get any problem .. always work ... that even made me wonder more,
Please help Me figure the problem where and why ... thank you..
Server Side [Node] :
const express = require('express');
const chalk = require('chalk');
const socketio = require('socket.io')
require('dotenv').config();
const PORT = process.env.PORT || 5000;
const app = express();
app.use(express.static(__dirname + '/public'))
const server = app.listen(PORT, () => {
console.log(chalk.yellowBright.inverse.bold(`Server is Running on PORT ${PORT}`))
})
function writeToDisk(dataURL, fileName) {
var fileExtension = fileName.split('.').pop(),
fileRootNameWithBase = './uploads/' + fileName,
filePath = fileRootNameWithBase,
fileID = 2,
fileBuffer;
// #todo return the new filename to client
while (fs.existsSync(filePath)) {
filePath = fileRootNameWithBase + '(' + fileID + ').' + fileExtension;
fileID += 1;
}
dataURL = dataURL.split(',').pop();
fileBuffer = new Buffer(dataURL, 'base64');
fs.writeFileSync(filePath, fileBuffer);
console.log('filePath', filePath);
}
const io = socketio(server)
io.on('connect', (socket) => {
console.log("Client Has Been Connected")
socket.emit('messageFromServer', { text:'You Are Connected To The Server!'})
socket.on('fromClient',(data)=>{
console.log(chalk.red.bold(data))
if (data.data.video) {
console.log(chalk.red.bold("Video Found"))
writeToDisk(data.data.video.dataURL, fileName + '.webm');
}
})
})
Client Side [Javascript]
var recordButton = document.getElementById('start-recording');
var stopButton = document.getElementById('stop-recording');
var local_video = document.querySelector("#local-video")
const socketio = io('http://localhost:3000/')
console.log('Hello World')
socketio.on('connect', () => {
console.log(socketio.id)
})
function invokeGetDisplayMedia(success, error) {
var displaymediastreamconstraints = {
video: {
displaySurface: 'monitor', // monitor, window, application, browser
logicalSurface: true,
cursor: 'always' // never, always, motion
}
};
displaymediastreamconstraints = {
video: true
};
if (navigator.mediaDevices.getDisplayMedia) {
navigator.mediaDevices.getDisplayMedia(displaymediastreamconstraints).then(success).catch(error);
}
else {
navigator.getDisplayMedia(displaymediastreamconstraints).then(success).catch(error);
}
}
function captureScreen(callback) {
invokeGetDisplayMedia(function (screen) {
callback(screen);
}, function (error) {
console.error(error);
alert('Unable to capture your screen. Please check console logs.\n' + error);
});
}
function startRecording() {
captureScreen(function (stream) {
mediaStream = stream;
local_video.srcObject = stream;
var videoOnlyStream = new MediaStream();
stream.getVideoTracks().forEach(function (track) {
videoOnlyStream.addTrack(track);
});
recordVideo = RecordRTC(videoOnlyStream, {
type: 'video/webm',
canvas: {
width: 1280,
height: 720
},
mandatory: {
// chromeMediaSource: 'screen',
minWidth: 1280,
minHeight: 720,
maxWidth: 1920,
maxHeight: 1080,
minAspectRatio: 1.77
},
recorderType: !!navigator.mozGetUserMedia ? MediaStreamRecorder : WhammyRecorder
});
recordVideo.startRecording();
stopButton.disabled = false;
});
}
function stopRecording() {
recordButton.disabled = false;
stopButton.disabled = true;
// stop video recorder
recordVideo.stopRecording(function () {
recordVideo.getDataURL(function (videoDataURL) {
var files = {
video: {
type: recordVideo.getBlob().type || 'video/webm',
dataURL: videoDataURL
}
};
const data = JSON.stringify(files)
console.log(data)
socketio.emit('fromClient', { "message": "Sent from client!", "data": data });
console.log('EMIT: fromClient');
if (mediaStream) mediaStream.stop();
});
});
}
recordButton.onclick = function () {
recordButton.disabled = true;
startRecording();
}
stopButton.onclick = function () {
stopButton.disabled = true;
stopRecording();
}
HTML :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RealTime Record</title>
</head>
<body>
<center>
<h1>Testing Recording</h1>
</center>
<center>
<div class="record-action">
<button id="start-recording">Start Recording</button>
<button id="stop-recording" disabled>Stop Recording</button>
<button id="fromClient">From Client</button>
</div>
<video id="local-video" autoplay style="border: 1px solid rgb(15, 158, 238);"></video>
</center>
<script src="RecordRTC.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="client.js"></script>
</body>
</html>

Nest.js equivalent program for below Node snippet

Can someone please help and tell me how I can write the following code snippet which is written as a node application to write as a nest application with just WebSockets and gateway class?
var webSocketsServerPort = 8080;
var webSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
});
server.listen(webSocketsServerPort, function() {
console.log(
new Date() + ' Server is listening on port ' + webSocketsServerPort
);
);
});
var wsServer = new webSocketServer({
httpServer: server
});
wsServer.on('request', function(request) {
var connection = request.accept(null, request.origin);
connection.on('message', function(data) {
var message = JSON.parse(data.utf8Data);
});
connection.on('close', function(connection) {});
EDIT:
In main.ts I wrote this :
app.useWebSocketAdapter(new WsAdapter(app));
This is how my gateway class looks like:
import { WebSocketGateway, WebSocketServer, OnGatewayInit, OnGatewayDisconnect, OnGatewayConnection, SubscribeMessage } from "#nestjs/websockets";
import { Server } from "websocket";
import { Logger } from "#nestjs/common";
#WebSocketGateway(8080)
export class ChatterGateway implements OnGatewayInit, OnGatewayDisconnect, OnGatewayConnection {
#WebSocketServer() private server: server;
private logger: Logger = new Logger('ChatterGateway');
afterInit(server: server) {
this.logger.log('ChatGetway init');
}
handleConnection(client: any, data) {
this.logger.log('Client connected');
}
handleDisconnect(client: any) {
this.logger.log('Client disconnected');
}
#SubscribeMessage('request')
handleRequest(client: any, data) {
this.logger.log(data);
}
#SubscribeMessage('message')
handleMessage(client: any, data) {
this.logger.log(data);
}
}

How to setup node with webpack dev server?

I want to proxy all /bundle urls to webpack dev server.
I have followed the advice from this question which does the same thing.
However, I still can't see my publicFiles served from localhost:8081/bundle? The silly thing is I have another project not based on react which works just fine, but this just says:
Cannot GET /bundle/
when accessing localhost:8081/bundle .
If you can point out what I'm missing I would really appreciate it. It must be something silly since I know this has to work.
Working in development mode
Here is my webpack config
'use strict';
var webpack = require('webpack');
const autoprefixer = require('autoprefixer');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var CompressionPlugin = require('compression-webpack-plugin');
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
let getPlugins;
var isProd = (process.env.NODE_ENV === 'production');
console.log("Production: " + isProd);
let entryFill = null;
let publicPathFill = null;
if (isProd) {
entryFill = {
bootstrap: ['bootstrap/dist/css/bootstrap.css', 'bootstrap/dist/js/bootstrap.js'],
index: ['./src/bundle/index.tsx'],
vendor: ['react', 'react-dom', 'jquery', 'jquery-ui-bundle', "redux-thunk", 'redux', 'react-redux']
}
publicPathFill = "./dist/assets/bundle";
getPlugins = function () {
return [
new SWPrecacheWebpackPlugin(
{
cacheId: 'cleaning-website',
filename: 'service-worker.js',
maximumFileSizeToCacheInBytes: 4194304,
runtimeCaching: [{
handler: 'cacheFirst',
urlPattern: /[.]js$/
}],
}
),
new ExtractTextPlugin("site.css"),
new webpack.optimize.UglifyJsPlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
//new webpack.optimize.DedupePlugin(),
//new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.bundle.js'),
//new webpack.optimize.AggressiveMergingPlugin(),
new webpack.ProvidePlugin({
jQuery: 'jquery',
$: 'jquery',
jquery: 'jquery'
})
//new CompressionPlugin({
// asset: "[path].gz[query]",
// algorithm: "gzip",
// test: /\.js$|\.css$|\.tsx$/,
// threshold: 10240,
// minRatio: 0.8
//})
]
}
} else {
entryFill = {
bootstrap: ['bootstrap/dist/css/bootstrap.css', 'bootstrap/dist/js/bootstrap.js', 'webpack/hot/dev-server', 'webpack-dev-server/client?http://localhost:8081'],
index: ['./src/bundle/index.tsx', 'webpack/hot/dev-server', 'webpack-dev-server/client?http://localhost:8081'],
vendor: ['react', 'react-dom', 'jquery', 'jquery-ui-bundle', "redux-thunk", 'redux', 'react-redux', 'webpack/hot/dev-server', 'webpack-dev-server/client?http://localhost:8081']
}
publicPathFill = "http://localhost:8081/bundle/",
//publicPathFill = "/",
getPlugins = function () {
return [
new ExtractTextPlugin("site.css"),
new webpack.HotModuleReplacementPlugin()
]
}
}
module.exports = {
/**
* Entry for all client side code.
* #var {object} entry
*/
entry: entryFill,
plugins: getPlugins(),
output: {
path: publicPathFill,
filename: '[name].js',
libraryTarget: 'umd'
publicPath: 'http://localhost:8081/bundle/'
},
resolve: {
extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"],
//alias: {
// 'react': 'preact-compat',
// 'react-dom': 'preact-compat',
// 'react-router': 'preact-compat'
//}
},
module: {
loaders: [
// { test: /\.(jpe?g|png|gif|svg)$/i, loader: 'url?limit=10000!img?progressive=true'},
{ test: /\.css$/, loader: "style-loader!css-loader" },
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract(
//Need:?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5] to set the right name for each css!
"style",
"css!postcss-loader!sass")
},
// { test: /bootstrap-sass\/assets\/javascripts\//, loader: 'imports?jQuery=jquery' },
{ test: /\.tsx?$/, loader: "ts-loader" },
{
test: /\.(pug|png|ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader'
}
]
},
postcss: function () {
return [autoprefixer(
// { browsers: ['ie 10', 'firefox 20', 'safari 9.1','Chrome ] }
{ browsers: ['> 0%'] }
)];
}
};
and my webpack dev server running in node looks like:
import * as express from 'express';
import * as path from 'path'
let webpack = require('webpack');
let WebpackDevServer = require('webpack-dev-server');
let proxy = require('proxy-middleware');
let url = require('url');
let config = require('../../../webpack.config.js');
import { post } from "./post";
import { pages } from "./pages";
module.exports = function (app: any, passport: any) {
var router = express.Router();
post(router, passport);
pages(router);
if (process.env.NODE_ENV === 'development') {
let base = path.join(__dirname, "..", "..", "assets");
console.log("Base : " + base);
//console.log(__dirname);
let server = new WebpackDevServer(webpack(config), {
//contentBase: base,
hot: true,
quiet: false,
noInfo: false,
publicPath: "/bundle/",
stats: { colors: true }
});
server.listen(8081, "localhost", function () { });
app.use('/bundle', proxy(url.parse('http://localhost:8081/bundle')));
}
app.use('/', router);
};
I serve the html page like so:
import { createStore, bindActionCreators, applyMiddleware } from 'redux';
import { routerReducer } from 'react-router-redux'
import thunkMiddleware from 'redux-thunk'
import * as path from 'path'
import * as fs from "fs";
import { Routes, Navigation, RootReducer } from "../../client/index";
export function pages(router) {
router.get('/*', function (req: any, res: any, next) {
let initial = {};
const store = createStore(RootReducer, initial, applyMiddleware(thunkMiddleware))
const body = ReactDOMServer.renderToString(
<Provider store={store}>
<StaticRouter location={req.url}>
<Routes/>
</StaticRouter>
</Provider>
)
//const nav = ReactDOMServer.renderToString(
// <Navigation/>
//)
const nav = ReactDOMServer.renderToString(
<div> Nav</div>
)
console.log("Body:");
console.log(body);
//const state = store.getState()
const state = {};
res.send(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Clement Cleaning</title>
<meta name="description" content="A cleaning business">
<meta name="author" content="Mortonproductions">
<script src="/bundle/bootstrap.js"></script>
<link rel="stylesheet" href="/bundle/site.css">
</head>
<body>
<header>
<h1>
Clement Cleaning
</h1>
<h2>
A cleaning business based in Loch Lomond
</h2>
</header>
<nav>
<div id="react-nav">${nav}</div>
</nav>
<section>
<div id="react-router">${body}</div>
</section>
<footer>
Progressive web app produced my morton productions
</footer>
<script>window.__REDUX_STATE__ = ${JSON.stringify(state)}</script>
<script src="/bundle/vendor.bundle.js"></script>
<script src="/bundle/index.js"></script>
</body>
</html>`
)
});
}

Resources