Javascript Globals and Socket.io - javascript

Is there any "globals" function in Javascript which is similar to PHP globals that would apply in this example?
var app = require('http').createServer(handler),
io = require('socket.io').listen(app),
fs = require('fs'),
querystring = require('querystring');
app.listen(8000);
var content = '';
function handler(req, res) {
io.sockets.on('connection', function (socket) {
if(req.method == 'POST') {
var fullBody = '';
req.on('data', function(chunk) {
fullBody += chunk.toString();
});
req.on('end', function() {
var decodedBody = querystring.parse(fullBody);
console.log(decodedBody);
socket.emit('user-aaa5c8bbffe4db9', fullBody);
});
}
});
fs.readFile(__dirname + '/index.html',
function(err, data) {
if(err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
I wrote a PHP app but I want to have notifications through socket.io but I don't want to rewrite the app for Node.js (yet) so I setup a Node server which the PHP will send a POST to and then the server will send the notification via Socket.io. I've tested the server with basic scripts and they do work. I've also tried moving the "io.sockets.on('connection', function (socket) {" inside the IF statement:
req.on('end', function() {
var decodedBody = querystring.parse(fullBody);
console.log(decodedBody);
io.sockets.on('connection', function (socket) {
socket.emit('user-aaa5c8bbffe4db9', fullBody);
});
});
But that did not produce "instant" results, the notifications would come in to the client after a page refresh.
Client is a simple:
socket.on('user-<?php echo $_SESSION['user_display_id']; ?>', function (data) {
alert(data);
$('#events').html(data);
});
Any help would be greatly appreciated

To answer your first question. No there is no global in JavaScript. All the variables that are in scope where the function is defined will be available in that function.
http://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/

In node.js there's the object global.
You can assign to its property some values and they will be accesible everywhere, but I think it is not best practice.

Related

Socket IO - NodeJS require external script?

I have a question regarding requiring scripts to the NodeJS / Socket.IO Server.
In PHP I can add the line require('somefile.php');
Is there any option to include any JS files to the NodeJS/Socket.IO server? My server code currently has over 500 lines, I want to add a Require for each Socket.On to make it easier to read.
Is there a disadvantage?
Thanks,
David :))
You can in this way,
Your IO Connection file,
var module1 = require('file1.js');
var module2 = require('file2.js');
io.on('connection', function (socket) {
module1(socket);
module2(socket);
})
file1.js,
module.exports = function (socket) {
socket.on('createroom', function (data) {
console.log("create room");
});
}
file2.js,
module.exports = function (socket) {
socket.on('play', function (data) {
console.log("play");
});
}

Integrate JSON response into Node.js/Express.js response

When I type somedomain.com/some_api_url?_var1=1 into a browser, the response is {"1":"descriptive string"}, where 1 is a numerical index variable whose value could range from 1 to n. And where "descriptive string" is some text that summarizes what the index represents.
How can I integrate the JSON response from the somedomain.com/some_api_url?_var1=1 api url into the very simple Node.js and Express.js example below?
For testing purposes, the very simple app.js shown below returns "Hello World" when the user requests http : // localhost : 3000 from their web browser. What specific changes need to be made to the code below so that the web browser responds to the request with:
Index is: 1
Description is: descriptive string
instead of responding with "Hello World"?
Here is the current code for app.js:
var express = require('express');
var http = require('http');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
Here is my current attempt, which results in the console printing Got a response: undefined, and with the browser remaining hung up because nothing is returned to the browser as a response:
var express = require('express');
var http = require('http');
var app = express();
app.get('/', function (req, res) {
var url = 'somedomain.com/some_api_url?_var1=1';
http.get(url, function(res){
var body = '';
res.on('data', function(chunk){
body += chunk;
});
res.on('end', function(){
var fbResponse = JSON.parse(body);
console.log("Got a response: ", fbResponse.picture);
});
}).on('error', function(e){
console.log("Got an error: ", e);
});
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
The get example code was adapted from the example at this link.
You actually forgot to return response res.send(data). Change you endpoint code like this. Also use different variable name for internal response object. I am using response here.
app.get('/', function (req, res) {
var url = 'somedomain.com/some_api_url?_var1=1';
http.get(url, function(resonse){
var body = '';
resonse.on('data', function(chunk){
body += chunk;
});
resonse.on('end', function(){
var body = JSON.parse(body);
var text = '';
for (var key in body){
text += 'Index is: ' + key +
'\nDescription is: ' + body[key]
}
// The Description is: "descriptive string"
console.log("Got a response: ", fbResponse);
res.send(text);
});
}).on('error', function(e){
console.log("Got an error: ", e);
});
});
Try this code with express 4.14.0
As #Zohaib-Ijaz pointed out, res is redefined and won't work for the res.send without a rename. This code also calls itself for demo purposes (so you can ignore app.get('/some_api_url', for the moment.
Then once the http.get is done, work with the object and print as you like. Keep in mind this code is not defensive against errors in the JSON.
var express = require('express');
var http = require('http');
var app = express();
const PORT = 3000;
app.get('/', function (req, res) {
var url = `http://localhost:${PORT}/some_api_url?_var1=1`;
http.get(url, function (resInner) {
var body = '';
resInner.on('data', function (chunk) {
body += chunk;
});
resInner.on('end', function () {
var fullResponse = JSON.parse(body); // {"343",:"I've heard 344 is more"}
// code to pair the keys with their data in plain js
var indexKeys = Object.keys(fullResponse);
var replies = indexKeys.map((key) => {
return `Index is ${key}\nDescription is ${fullResponse[key]}`;
});
//note this injection of a <pre> tag is just so modern browsers
// will respect the newlines. it is not an HTML document or JSON
res.send(
`<pre>${replies.join("\n")}</pre>`
);
});
}).on('error', function (e) {
console.log("Got an error: ", e);
});
});
app.get('/some_api_url', (req, res) => {
var var1 = req.query.var1 || "343";
var value = `I've heard ${parseInt(var1) + 1} is more`;
var reply = {};
reply[var1] = value;
res.send(JSON.stringify(reply));
});
app.listen(PORT, function () {
console.log(`Example app listening on port ${PORT}!`);
});
You seem to be mixing up Express, native HTTP module, and HTTP client.
Here is the serverside code for sending the response you are looking for.
var express = require('express');
var http = require('http');
var app = express();
// our "database"
var database = ['APPLE', 'BOOK', 'CAT', 'DOG', 'ELEPHANT'];
app.get('/', function (req, res) {
// apply query parsing only of the query parameter is specified
if ('itemId' in req.query) {
var itemId = req.query.itemId;
// index less than 0 will not yield anything from our "database"
if (itemId < 0) {
res.status(400).send('Invalid item id');
// the item index corresponds to one of the items in the "database"
} else if (itemId < database.length) {
var result = 'Index: ' + itemId + '<br>Description: ' + database[itemId];
res.send(result);
// index exceeds the size of the array, so nothing will be found
} else {
res.status(404).send('Item not found');
}
// render the default homepage
} else {
res.send('Request format: http://localhost:3000/?itemId=n');
}
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
To see it in action, load http://localhost:3000/?itemId=0 in the browser. Valid itemId values are 0 to 4.

How can a http.createServer receive data from needle.post using fs.createReadStream

I want to send an image from a nodejs server to another nodejs server.
I understand there are a lot of solutions, but I hoping to find out how to do it in the following way:
Server A (Sender)
Option 1
needle.post('http://127.0.0.1:8000', fs.createReadStream('test.png'), function(err, resp, body) {
});
Option 2
var reader = fs.createReadStream('test.png');
reader.pipe(request.post('http://127.0.0.1:8000'));
Server B (Receiver)
http.createServer(function(req, res) {
if (req.method === 'PUT' || req.method === 'POST') {
req.on('data', function(chunked) {
// I got nothing here
});
res.on('data', function(chunked) {
// I got nothing here
});
}
}).listen(8000, function() {
console.log('Listening for requests');
});
The problem is that if I read the file data that is sent over using fs.createReadStream, I am not able to receive any data from Server B.
[Edit] Also need to know how to handle the above using Express
You can try to create the fs.createWriteStream() and assign to req.pipe().
...
var saveTo = './test.png',
ws = fs.createWriteStream(saveTo);
ws.on('close', function () {
cb();
});
req.pipe(ws);
...
As mentioned by zangw in comments, the script actually works. My bad that my test.png is blank

nodejs write after request end error

I am facing problem of write after request end in nodejs :
I have a server.js file , which sends request to other js file (say abc.js) which sends response back to server.js file and then server.js file writes the resoponse and then end response.
my problem is if I write response in abc.js and end it there only it works fine, but if it is in sererconf.js it doesn't.
Let me make it clear that I get this bug only when i send 20-30 requests at a time. I want to know the logic behind it, I searched a lot, but no nice answer found, any help will be appreciated.
server.js full code:
/* create HTTP server */
var httpd = http.createServer(function(req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.writeHead(200, {"Content-Type" : "application/json"});
}).listen(3800);
/* send request to the file mentioned in url*/
httpd.on('request', function(req, res) {
urll = __dirname + '/..' + req.url;
fs.exists(urll, function (exists) {
if(exists){
var server = require(urll);
server.get(req,res);
}
});
module.exports = {
result : function(result){
if(Array.isArray(result)){
for(var key in result){
result[key] = JSON.parse(result[key]);
}
}
result = JSON.stringify(result);
res.write(result ,function(err) { if(!err) res.end(); });
},
};
});
**apps.js code**:
var constants = require('./lib/constant.js');
var APP_PATH = constants.APP_PATH;
module.exports = {
get : function(req) {
req.on('data', function(chunk) {
var hash = chunk;
hash = JSON.parse(hash);
var id = hash.id;
dirPath = APP_PATH + id;
fs.exists( dirPath, function (exists) {
if(exists)
read_app_dir(dirPath);
else
taskDone([]);
});
});
}
};
function read_app_dir(app_dir){
fs.readdir(app_dir,function(err, list){
if (err) {
httpd.log.info('cannot read apps dir at s_apps = '+err);
}else{
create_new_obj(list,app_dir);
}
});
}
function create_new_obj(list, app_dir){
appFilesObj = [];
var i = 0;
list.forEach(function(file) {
i=i+1;
file = app_dir +'/' +file;
appFilesObj.push(file);
if(i == Object.keys(list).length)
read_app_files(appFilesObj);
});
}
function read_app_files(appFilesObj,app_dir){
var apps = [];
var i = 0;
if(Object.keys(appFilesObj).length > 0){
appFilesObj.forEach(function(appfile) {
read_file(appfile,function(data){ i=i+1;
apps.push(data);
if(i == Object.keys(appFilesObj).length)
taskDone(apps);
});
});
}else{
taskDone([]);
}
}
function read_file(file,callback){
fs.readFile(file,'utf8', function (err, data) {
if (err)
httpd.log.info('cannot read file at s_apps = '+err);
else
callback(data);
});
}
function taskDone(apps){
var httpd = require(__dirname + '/server.js');
httpd.result(apps);
}
if I do res.write and res.end in this file in taskDone() then it works fine.
Thanks in advance :)
The problem with above code was, that I was sending back response by calling an exported function of server.js
like this:
var httpd = require(__dirname + '/server.js');
httpd.result(apps);
where result() is the function which I have exported in server.js to write response and end response
Instead of this, now I added a callback support while calling function of other files (ex-apps.js), so that I "res.write" and "res.end()" only when the actually called function gives back the response.
(I am not writing the whole code , please refer above code for difference in both)
httpd.on('request', function(req, res) {
urll = __dirname + '/..' + req.url;
fs.exists(urll, function (exists) {
if(exists){
var server = require(urll);
server.get(req,res,function(result){
res.write(result);
res.end();
});
}
});
**apps.js**
get : function(req, callback) {
req.on('data', function(chunk) {
//when task is done and taskDone() function is called I just callback() the result
function taskDone(result){
callback(result);
}
}
}
When I was sending result back by calling a function of server.js and then writing the response...I don't know how..but somehow server was getting confused in multiple requests and saying "write after end" error...while the end was called by some other user's request.
I may be wrong, but this is what I concluded from this :)
I hope this may help others.

Socket.io Identify User for Socket

I write some code example that identifi connected users via socket.io... So now I must write a code on index page to comunicate with users.
The code is below and HOW to send a message to user[1] "Welcome" and for user[2] "HI men" and also limit connection fr 2 users. so when 2 user connected then anybody else cant connect..
Index.html:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect();
var users;
socket.on('hello', function (data) {
console.log(data.hello);
});
socket.on('listing', function (data) {
users = data;
});
socket.on('chat', function (message) {
console.log(message);
});
socket.on('message', function (message) {
console.log(message);
});
function chat (message) {
socket.emit('chat', message);
}
function message (user, message) {
socket.emit('message', {
user: user,
message: message
});
}
</script>
app.js
var express = require('express');
var app = express.createServer();
var io = require('socket.io').listen(app);
app.listen(3000);
app.use(express.static(__dirname));
var users = {};
var userNumber = 1;
function getUsers () {
var userNames = [];
for(var name in users) {
if(users[name]) {
userNames.push(name);
}
}
return userNames;
}
io.sockets.on('connection', function (socket) {
var myNumber = userNumber++;
var myName = 'user#' + myNumber;
users[myName] = socket;
socket.emit('hello', { hello: myName });
io.sockets.emit('listing', getUsers());
socket.on('chat', function (message) {
io.sockets.emit('chat', myName + ': ' + message);
});
socket.on('message', function (data) {
users[data.user].emit('message', myName + '-> ' + data.message);
});
socket.on('disconnect', function () {
users[myName] = null;
io.sockets.emit('listing', getUsers());
});
});
app.listen(process.env.PORT);
You can start by taking a look at how to configure authorization with Socket.io. The handshakeData provided by the callback can be modified there (ie: add a username property), and any changes will be accessible via socket.handshake in your app.js (via the object passed in to the callback for io.sockets.on('connection',..). Using request header information that's also accessible from the handshakeData, you can set user values within the authorization callback (ie: from a database) so you can identify the user for the given socket in your app.js.
Here's a similar example
I know it has been a long time since you asked this, but just 4 days ago I published a module for node js, express and socket.io which manages that exactly thing you wanted. Check the Usage and Example; I hope you will find this module helpful!
You can install it via NPM socket.io.users This is a node js module for socket.io applications. One user per client.
Some of the usage code:
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var socketUsers = require('socket.io.users');
// ...
socketUsers.Session(app); // IMPORTANT !
// ...
var rootIo = require('socket.io')(server); // default '/' as namespace.
var chatIo = rootIo.of('/chat');
var rootUsers = socketUsers.Users; /* default '/' as namespace.
Each namespace has ITS OWN users object list,
but the Id of a user of any other namespace may
have the same value if request comes from the same client-machine-user.
This makes easy to keep a kind of
synchronization between all users of all the different namespaces. */
var chatUsers = socketUsers.Users.of('/chat'); //
rootIo.use(socketUsers.Middleware());
/* IMPORTANT but no errors if you want
to skip it for a io.of(namespace)
that you don't want the socket.io.users' support. */
chatUsers.use(socketUsers.Middleware());
chatUsers.on('connected',function(user){
console.log(user.id + ' has connected to the CHAT');
user.store.username = 'username setted by server side'; /*at the store
property you can store any type of properties
and objects you want to share between your user's sockets. */
user.socket.on('any event', function(data){
/*user.socket is the current socket, to get all connected sockets from this
user, use: user.sockets */
});
chatIo.emit('set username',user.store.username);
});
rootUsers.on('connected',function(user){
console.log('User has connected with ID: '+ user.id);
});
rootUsers.on('connection',function(user){
console.log('Socket ID: '+user.socket.id+' is user with ID: '+user.id);
});
rootUsers.on('disconnected',function(user){
console.log('User with ID: '+user.id+'is gone away :(');
});
//...server.listen blabla..

Categories

Resources