Print array in node js server - javascript

Hi I have a website from witch I can send a message to node js server and there the message is saved in a a array. When a new message is sent to the server the old message in the array is overwritten by the new message. The array has to contain new and old messages.
The output of console after sending message
const http = require('http');
const { Socket } = require('socket.io');
const WebSocketServer = require('websocket').server;
var steviloSporocil = 0;
const sporocila=[];
const server = http.createServer();
console.log('Server is on port 3000')
server.listen(3000);
const wsServer = new WebSocketServer({
httpServer: server
});
wsServer.on('request', function(request) {
const connection = request.accept(null, request.origin);
connection.on('message', function(message) {
sporocila[steviloSporocil]=[message.utf8Data];
steviloSporocil++;
for (let i = 0; i < steviloSporocil; i++) {
connection.sendUTF(sporocila[i]);
console.log('Received Message:', sporocila[i]);
}
});
connection.on('close', function(reasonCode, description) {
console.log('Client has disconnected.');
});
});
<?php ob_start() ?>
<?php $titel="Chat"; ?>
<div class="chat-main" id="text"></div>
<form name='form' method='post' class="form">
<div class="form-group">
<input type="text" class="form-control" id="textbox" name="chat" placeholder="Chat">
<button type="button" class="btn btn-primary" name="gumb" id="gumb" onclick="Poslji()" autocomplete="off">Send</button>
</div>
</form>
<script>
function Poslji(){
const ws = new WebSocket('ws://localhost:3000');
ws.onopen = function() {
console.log('WebSocket Client Connected');
ws.send(document.getElementById('textbox').value);
};
ws.onmessage = function(e) {
console.log("Received: '" + e.data + "'");
document.getElementById('text').innerHTML=e.data;
};
}
</script>
<?php
$content=ob_get_clean();
require "layout.html.php";
?>

If I understood everything, here how to solve your problem:
you take all previous message at the specified index and add the new one at the end. If you want to add it at the top, then just invert the two lines.
sporocila[steviloSporocil] = [
...sporocila[steviloSporocil],
message.utf8Data
];

You are sending the messages in the array to the client separately using a for-loop and connection.sendUTF(sporocila[i]); and then displaying the last message received using document.getElementById('text').innerHTML=e.data;.
Are you suprised then that your website only shows the last item in the array?
Why not send the entire array using JSON.stringify and then JSON.parse on the client?

Related

Node js not sendin messages to clients

Hi I am making a simple chat website with node js. I want everyone to see posted messages. The messages are stored in a array and then displayed on the website. The problem is that when a message is posted no one can see it. A user will be able to see it after posting a new message. Can someone help?
const http = require('http');
const { Socket } = require('socket.io');
const WebSocketServer = require('websocket').server;
var steviloSporocil = 0;
let sporocila=[];
const server = http.createServer();
console.log('Server is on port 3000')
server.listen(3000);
const wsServer = new WebSocketServer({
httpServer: server
});
wsServer.on('request', function(request) {
const connection = request.accept(null, request.origin);
connection.on('message', function(message){
sporocila.push(message.utf8Data);
connection.sendUTF(JSON.stringify(sporocila));
console.log('Received Message:', JSON.stringify(sporocila));
});
connection.on('close', function(reasonCode, description) {
console.log('Client has disconnected.');
});
});
<?php ob_start() ?>
<?php
$titel="Chat";
$nekaj=$_SESSION['uporabnik'];
?>
<div class="chat-main" id="text"></div>
<form name='form' method='post' class="form">
<div class="form-group">
<input type="text" class="form-control" id="textbox" name="chat" placeholder="Chat">
<button type="button" class="btn btn-primary" name="gumb" id="gumb" onclick="Poslji()" autocomplete="off">Send</button>
</div>
</form>
<script>
var myInput = document.getElementById("textbox");
var up='<?php echo $nekaj; ?>';
function Poslji(){
if(myInput && myInput.value){
const ws = new WebSocket('ws://localhost:3000');
ws.onopen = function(){
ws.send(up+": "+document.getElementById('textbox').value+"<br>");
};
ws.onmessage = function(e) {
const arr=JSON.parse(e.data);
console.log("Received: '"+e.data+"'");
document.getElementById('text').innerHTML=arr;
};
}
}
</script>
<?php
$content=ob_get_clean();
require "layout.html.php";
?>

running function more than one times returns "error: Can't set headers after they are sent"

Program runs as it should until I try to use the function once again and it returns the error: Can't set headers after they are sent.
I'm creating this app to familiarize myself with nodejs and javascript and I've been reading about the error and it seems to be an issue when sending more than one response to a request. I started using res.setHeader before knowing this, but I read that res.header could avoid this problem, it didn't solve it but I kept it.
HTML:
<!doctype html>
<head>
<link rel="stylesheet" type="text/css" href="youtube2music.css">
<title>
Youtube2Music
</title>
</head>
<body>
<div id="cabeza">
<h1>
Youtube 2 Music
</h1>
<p>
just paste your link below and download your song.
</p>
</div>
<div id="down-part">
<input id="myUrl" class='myUrl-input'>
</input>
<button type="button" class="download_button">
Download
</button>
</div>
</body>
<script src='youtube2music.js'></script>
</html>
Javascript:
var urlinput = document.querySelector('.myUrl-input'); // gets url inputbox
var button = document.querySelector('.download_button'); // gets download button
button.addEventListener('click', () => {
console.log(urlinput.value); // prints in console the url
sendUrl(urlinput.value); // sends url to function to start the request
});
// function to make requst
function sendUrl(URL){
window.location.href = `http://localhost:4000/?URL=${URL}`; // makes the video request to nodejs server
}
index.js < node file:
var eventEmitter = new events.EventEmitter();
var sfn;
appi.use(cors());
const {app, BrowserWindow} = require('electron')
function createWindow(){
let win = new BrowserWindow({width:800, height:600});
win.loadFile('index.html');
}
app.on('ready', createWindow)
appi.listen(4000, () => {
console.log('server at port 4000');
});
appi.get('/',(req,res)=>{
var URL = req.query.URL;
ytdl.getInfo(URL, function(err,info){
if(err) throw err;
var songTitle = info.title;
sfn = filenamify(songTitle);
eventEmitter.emit('name_ready');
});
var startDownload = function(){
let stream = ytdl(URL, {
quality: 'highestaudio',
});
res.header('Content-Disposition', 'attachment; filename=' + sfn + '.mp3');
res.header('Content-type', 'audio/mpeg');
proc = new ffmpeg({source: stream})
proc.withAudioCodec('libmp3lame').toFormat('mp3').output(res).run();
}
eventEmitter.on('name_ready', startDownload);
})
as it is works for the first input but asking for another output results in error, why is it really returning this error and how can it be avoided?
There are several problems with your current setup:
Try not to use event emitter for signaling events within an HTTP request, it wasn't made for this.
With HTTP requests, try not to use global variables for data received during the request, when two requests come in at the same time, they may get confused and get sent the wrong data.
appi.listen(4000, () => {
console.log('server at port 4000');
});
appi.get('/', (req,res)=> {
const { URL } = req.query;
ytdl.getInfo(URL, (err,info) => {
if(err) throw err;
const songTitle = info.title;
const sfn = filenamify(songTitle);
let stream = ytdl(URL, {
quality: 'highestaudio',
});
res.set('Content-Disposition', 'attachment; filename=' + sfn + '.mp3');
res.set('Content-type', 'audio/mpeg');
const proc = new ffmpeg({source: stream})
proc.withAudioCodec('libmp3lame').toFormat('mp3').output(res).run();
});
})

information from a JavaScript site to the NODE.js server

I have a site in javascript where I get information from a Rest API (JSON)
I would like to make this information available to my server (A node.js that I have created that connects to the database)
It is my first time working with web development; I would like to know how I make the connection between the two?
front end
<!DOCTYPE html>
<head>
<style>
.bodyFrame {
margin: 40px;
}
.headerLabel {
font-weight: bold;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div class="bodyFrame">
<h2 style="text-align:center;">WIDS JSON Retrieval Example</h2>
<button type="button" onclick="makeServiceCall()">Retrieve JSON Data</button>
<br /><br />
<label class="headerLabel">Programs</label>
<ul id="programUL"></ul>
<div>
<script>
function makeServiceCall() {
var url = "http://widsservicedev.yaharasoftware.com/WidsService/JSON/GetPortagePrograms/?apikey=104043F0-9C24-4957-879D-046868973CC4&callback";
$.getJSON(url, function (data) {
//var myArray = [];
//myArray[0] = data;
parseProgramData(data, url);
});
}
function parseProgramData(jsonData, url) {
$("#dataHeader").empty();
$("#dataHeader").append('<b>' + url + '</b>');
var programUL = document.getElementById("programUL");
for (var pgmIndex = 0; pgmIndex < jsonData.Programs.length; pgmIndex++) {
var pgmLi = document.createElement("li");
var program = jsonData.Programs[pgmIndex];
var programInfoRevision = program.ProgramInfoRevisions[0];
var numberTitle = programInfoRevision.ProgramNumber + " " + programInfoRevision.ProgramTitle;
pgmLi.appendChild(document.createTextNode(numberTitle));
programUL.appendChild(pgmLi);
var linebreak = document.createElement("br");
pgmLi.appendChild(linebreak);
var poLabel = document.createElement("label");
poLabel.appendChild(document.createTextNode("Program Outcomes"));
poLabel.classList.add("headerLabel");
pgmLi.appendChild(poLabel);
var pgmOutcomeUL = document.createElement("UL");
pgmLi.appendChild(pgmOutcomeUL);
for (var poIndex = 0; poIndex < program.ProgramOutcomes.length; poIndex++) {
var poLi = document.createElement("li");
poLi.appendChild(document.createTextNode(program.ProgramOutcomes[poIndex].Description));
pgmOutcomeUL.appendChild(poLi);
}
}
}
</script>
</body>
<footer>
</footer>
node.js
var express = require('express');
var app = express();
app.get('/', function (req, res) {
var sql = require("mssql");
// config for your database
/* var config = { user: 'papercut', password: 'Portage.2018', server: 'devsqlcl2:1433', database: 'AgrM6', port: "1433", dialect:",ssql", dialectOptiond:"SQLEXPRESS" };*/
// connect to your database
sql.connect('mssql://xxx:xxxx#xxxx:1433/xxx', function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query('select * from dbo.balance_papercut', function (err, recordset) {
if (err) console.log(err)
// send records as a response
res.send(recordset);
});
});
});
var server = app.listen(5000, function () { console.log('Server is running..'); });
Thank you.
Well to make those data available to the server you basically have to sent a request to the server containing those data. Since you want to sent data to the server you most likely need to use a POST request. There are more informations here about how to send such a request.
On the server side you need to an endpoint listening for a post request. You can find a lot of information about how to do this on the server on google.
A simple way to accomplish connection between frontend and backend is to create api-endpoints. You have already done so with your app.get('/', function (req, res).
You can do a similar one for sending data to the server. The http method used to send data to the server is generally POST. You can read more about the http methods here:
https://restfulapi.net/http-methods/
A good guide I stumbled upon a few weeks ago are this one:
https://codeforgeek.com/2014/09/handle-get-post-request-express-4/
In this example it does exactly what you're trying to accomplish, by sending data from a script in a static html-file to an Express server.

I need the route data in a node client between client to correct connected user

I am trying to build a gnuchess web api and bind it to a graphical web interface. Trought a websocket the users will connect and when connecting the server-websocket will launch a "gnuchess" as subprocess. Then I would like to communicate with the gnuchess's stdin/stdout and send the stream to the user. But as the code is today it only starts new gnuchess's but I could only write to one of them (with all connected clients I could do that)
I have this code node-code:
var http = require("http");
var ws = require("./");
var fs = require("fs");
var process = require('child_process');
theglobal = "";
var ls = "";
// Web server
http.createServer(function (req, res) {
fs.createReadStream("index.html").pipe(res)
}).listen(8080);
// Socket stuff
var server = ws.createServer(function (connection) {
connection.on("text", function (str) {
var tmp_cmd = str.split(" ")[0];
var tmp_string = str.substr(str.indexOf(" ") + 1);
console.log(tmp_cmd)
console.log(tmp_string)
if (tmp_cmd == "move") {
ls.stdin.write(tmp_string + "\n");
connection.sendText(str);
}
if (str == "start") {
connection.sendText(str);
ls = process.spawn('/usr/games/gnuchess');
ls.stdout.on('data', function (chunk) {
broadcast(chunk)
});
}
})
});
server.listen(8081);
// Functions
// This broadcasts to all clients connected
function broadcast(str) {
server.connections.forEach(function (connection) {
connection.sendText(str)
})
}
HTML:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Chat example</title>
<script>
var connection
window.addEventListener("load", function () {
var nickname = prompt("Choose a nickname")
if (nickname) {
connection = new WebSocket("ws://"+window.location.hostname+":8081")
connection.onopen = function () {
console.log("Connection opened")
connection.send(nickname)
document.getElementById("form").onsubmit = function (event) {
var msg = document.getElementById("msg")
if (msg.value)
connection.send(msg.value)
msg.value = ""
event.preventDefault()
}
}
connection.onclose = function () {
console.log("Connection closed")
}
connection.onerror = function () {
console.error("Connection error")
}
connection.onmessage = function (event) {
var div = document.createElement("div")
div.textContent = event.data
document.body.appendChild(div)
}
}
})
</script>
</head>
<body>
<form id="form">
Message: <input size="50" id="msg"> <input type="submit" value="Submit">
</form>
</body>
</html>
But what happens is that it starts a new gnuchess for every user who connects (it should be like that) but the data routes to the first openeded gnuchess.
Could solve the problem by using a IRC bot and IRC server and use different channel for each game (#gnuchess_user1, #gnuchess_user2, etc..) But I think it's easier actually to solve it by making a method or own object for each user and route it in the websocket.
You should look at socket.io, it has built in support for rooms:
io.on('connection', function(socket){
socket.join('some room');
});
Which means you can broadcast to all sockets connected to that room. You don't have to spawn separate processes for these (it will be devastating for your performance..)
io.to('some room').emit('some event');
http://socket.io

Sending data through node.js tcp socket from html page

Hy, I'm asking because I want to clear my mind about net sockets in Node.js:
I have an easy server that replicates the data received. It looks like this:
var net = require('net');
var HOST = '127.0.0.1';
var PORT = 1337;
net.createServer(function(sock) {
console.log('CONNECTED: ' + sock.remoteAddress +':'+ sock.remotePort);
sock.on('data', function(data) {
console.log('DATA ' + sock.remoteAddress + ': ' + data);
sock.write('You told me: ' + data);
});
sock.on('close', function(data) {
console.log('CLOSED: ' + sock.remoteAddress +' '+ sock.remotePort);
});
}).listen(PORT, HOST);
console.log('Server listening on ' + HOST +':'+ PORT);
So, if I want to make a really easy html page like this:
<input type="text" name="data" value="" />
<input type="button" value="Send data" onclick="send()" />
<div id="result"></div>
Now I will click on the button and the page sends data to the server, and write the answer into the "result" div. What i need to write or use in the function "send()" (just in order to send the data and receive the answer)? I searched for things like this a lot, but wasn't lucky...
I need to add an http server to the server file maybe?
I recommend you use SockJS module in server and client side. Look this example for client:
var sock = new SockJS('YOUR_SOCKJS_URL');
sock.onopen = function() {
console.log('open');
};
sock.onmessage = function(e) {
console.log('message', e.data);
};
sock.onclose = function() {
console.log('close');
};
function send(){ // this for onclick="send()"
sock.send();
}
For server use Sockjs module. example:
var http = require('http');
var sockjs = require('sockjs');
var echo = sockjs.createServer({ sockjs_url: 'http://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js' });
echo.on('connection', function(conn) {
conn.on('data', function(message) {
conn.write(message);
});
conn.on('close', function() {});
});
var server = http.createServer();
echo.installHandlers(server, {prefix:'/echo'});
server.listen(9999, '0.0.0.0');

Categories