Cannot debug an anonymous function using node-inspector - javascript

Here is the simple demo server program that I am trying to step into using the node-inspector debugger:
var http = require('http');
var fs = require('fs');
http.createServer(function(req, res) {
res.writeHead(200, { 'Content-Type': 'text/html' });
var html = fs.readFileSync(__dirname + '/index.htm', 'utf8');
var message = 'Hello world...';
html = html.replace('{Message}', message);
res.end(html);
}).listen(1337, '127.0.0.1');
Try as I might, I cannot coax node-inspector to set a breakpoint (or alternatively, use the debugger statement) inside the passed anonymous function to the http.createServer(...) function call. I can set a breakpoint on the first line (e.g., var http = require...) the second line, and the fourth line (http.createServer...), but NOT inside the passed anonymous function.
First I tried pulling out the anonymous function and created a function expression like so:
var callback = function(req, res) {
...
}
and passed it to the
http.createServer(callback).listen(1337, '127.0.0.1');
That won't work either.
Finally, I tried naming the function like so:
var http = require('http');
var fs = require('fs');
function callback(req, res) {
res.writeHead(200, { 'Content-Type': 'text/html' });
var html = fs.readFileSync(__dirname + '/index.htm', 'utf8');
var message = 'Hello world...';
html = html.replace('{Message}', message);
res.end(html);
}
http.createServer(callback).listen(1337, '127.0.0.1');
And that works like a charm!
If this is an inherent limitation of node-inspector then that is a serious problem. I am hoping that someone can show me an easier way to debug rather than have to pull out the anonymous functions and name them at global level?

Related

issue child process inside a server on node.js

I have an executable library in C (sudo ./ads1256_test adc.txt) where data are acquired from an ADC, likewise these data are automatically save in a text file (adc.txt).
On the other hand, I have a server in node.js (see code) in which would like to execute this program when a button in the website is pressed. For this, I tried to implement this process using the child process .exec('sudo ./ads1256_test adc.txt') but it did not work. It apparently runs but the values saved in the file are always zero. That is totally different to the obtained result when I execute the same command in terminal. I would appreciate if anybody could help me.
//Importing the core modules
var express = require('express');
var path = require('path');
var sys = require('sys');
var fs = require('fs');
var util = require('util');
var sleep = require('sleep');
var app = express();
var exec = require('child_process').exec;
var spawn = require('child_process').spawn;
app.get('/', function(req,res){
res.sendFile(path.join(__dirname + '/public/index.html'));
});
//Static Directories
app.use(express.static(__dirname + '/public'));
app.post('/test', function (req, res) {
exec('sudo ./ads1256_test adc.txt');
});
//Server Starting
var server = app.listen(8080, function(err){
if(err){
console.log('Error starting http server');
} else{
console.log('Sever running at http://localhost:8080 ');
}
});
first thing first, fix your code to
- asynchronously handle the cp spawn
- show errors
Example with tree, may you adapt it to your binary and check the response, it should help you go forward.
app.post('/test', function (req, res) {
var cp = spawn('tree', []);
cp.stdout.pipe(res);
cp.stderr.pipe(res);
cp.on('close', function () {
res.end();
cp.stdout.unpipe();
cp.stderr.unpipe();
});
});

How do you use a Node.js variable on the client-side?

I'm relative new to NODEJS and I'm struggling with a basic problem, which is the correct use of global variables, I read a lot about it but it seems I can't make it work properly, I'll post some codes for a better view of the problem.
I have this simple js running as a server:
myapi.js
var http = require('http');
var express = require('express');
var app = express();
var exec = require('child_process').exec, child;
var fs = require('fs');
var jUptime;
var ipExp = require('./getDown');
var filesD = [];
var path = "/media/pi/01D16F03D7563070/movies";
app.use(express['static'](__dirname ));
exec("sudo /sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{print $1}'", function(error, stdout, stderr){
ip = stdout;
exports.ipAdd = ip;
console.log(ip);
});
app.get('/files', function(req, res) {
fs.readdir(path, function(err, files) {
if (err){
console.log("Non riesco a leggere i files");
}
filesD=files;
console.log(filesD);
});
res.status(200).send(filesD);
});
app.get('/up', function(req, res) {
child = exec("uptime -p", function(error, stdout, stderr){
jUptime = [{uptime: stdout}];
});
res.status(200).send(jUptime);
});
app.get('*', function(req, res) {
res.status(404).send('Richiesta non riconosciuta');
});
app.use(function(err, req, res, next) {
if (req.xhr) {
res.status(500).send('Qualcosa รจ andato storto');
} else {
next(err);
}
});
app.listen(3000);
console.log('Server attivo sulla porta 3000');
And then I have this JS used in a simple web page:
getDown.js
var ip = require('./myapi').ipAdd;
function gDownloads() {
var url;
var jqxhr;
var dat;
url = 'http://' + ip + '/files';
jqxhr = $.getJSON(url, function(dat) {
for(i=0; i<dat.length; i++){
$('#downLoad').append('<p>' + dat[i] + '</p>');
}
$('#bId').append(dat.length);
})
.done(function() {
console.log("OK");
})
.fail(function(data) {
console.log("Fallito: "+data);
})
};
The problem is that when I navigate to the html page that use getDown.js I get the following error on getDown.js
require is not defined
I need to pass the variable that contains the IP address in myapi.js to use it in getDown.js, I hope I explain myself good enough, thanks in advance.
require is global that exists in Node.js code, that is, on the javascript code executing in the server.
Your server will respond to the client and give it an HTML page to render. That HTML page could tell the browser to also request a javascript file from the server. When it receives that file, the client will execute it. The client does not have a require global (you can test it by opening up the console and typing require)
Using Browserify
Or you can write Node-style code, requiring your global like you're doing, but then run the code through browserify. This will create a new javascript bundle that can be executed by the client, so you should tell your html page to use that bundle instead of getDown.js.
Here is a basic example of doing using browserify like this.
module.js
function getIp() {
return 123456;
}
module.exports = {
getIp: getIp
};
main.js
var module = require('./module');
function getIp() {
var ip = module.getIp();
return ip;
};
console.log(getIp());
compile bundle
$ browserify main.js -o public/bundle.js
index.html
<script type="text/javascript" src="public/bundle.js"></script>
Global variable on the client
To use a global variable on the client which is known by the server, you can pass that variable to your rendering engine (possibly Jade if you're using Express) and have it interpolate that variable into a <script> tag which defines some globals. Leave a comment if that's the approach you'd prefer and I can add some more details.
Let me know if you have more questions!

node.js res.write doesn't work

To learn node js i make some exercise but have got a problem, the "res" variable work in index.js but doesn't work in the fs.exists function, why ?. Thanks for your responses.
server.js
var http = require("http");
global.PATH = __dirname;
http.createServer(function(req, res) {
var app = require("./index.js")(req, res);
res.end();
}).listen(8080);
index.js
var url = require("url");
var fs = require("fs");
module.exports = function(req, res){
if(req){
var pathname = url.parse(req.url).pathname.split("/");
pathname.splice(0,1);
var action = pathname[1];
fs.exists(PATH + "/" + pathname[0] + ".js" , function(exist){
var controller;
res.write('doesn\'t work');
if(exist)
{
if(!controller){
controller = require(PATH + "/controllers/" + pathname[0] + ".js" )();
if(controller[action])
controller[action]();
}
}
});
}
}
i don't know why some of you downvoted the question, because for a beginner some asynchronous patterns could be confusing...
first of all you should cache your require-call (as Seth mentioned).
global.PATH = __dirname;
var http = require("http");
var app = require("./index"); //omit .js, you don't need it
then you you index.js you are using fs.exists, which is asynchronous. that means, that the res.end() is called before your callback function inside fs.exists is reached, which means the request/response lifecylcle is over.
you could use fs.existsSync (not recommended!) or provide some callback which you call when done!
2 more things
the if(req) is unneccessary, there is always a request object!
you ALWAYS need to call the callback in your function, to make the response be sent!
server.js:
http.createServer(function(req, res) {
app(req, res, function () {
res.end();
});
}).listen(8080);
index.js:
var url = require("url");
var fs = require("fs");
module.exports = function(req, res, cb) { // see third cb-argument!
var pathname = url.parse(req.url).pathname.split("/");
pathname.splice(0,1);
var action = pathname[1];
fs.exists(PATH + "/" + pathname[0] + ".js" , function(exist){
var controller;
res.write('doesn\'t work');
if(exist)
{
if(!controller){
controller = require(PATH + "/controllers/" + pathname[0] + ".js" )();
if(controller[action])
controller[action]();
}
}
cb(); // whenever you're done call the callback
});
}

Node.js respond with asynchronous data

Recently I started learning a little bit about Node.js and it's capabilities and tried to use it for some web services.
I wanted to create a web service which will serve as a proxy for web requests.
I wanted my service to work that way:
User will access my service -> http://myproxyservice.com/api/getuserinfo/tom
My service will perform request to -> http://targetsite.com/user?name=tom
Responded data would get reflected to the user.
To implement it I used the following code:
app.js:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var proxy = require('./proxy_query.js')
function makeProxyApiRequest(name) {
return proxy.getUserData(name, parseProxyApiRequest);
}
function parseProxyApiRequest(data) {
returned_data = JSON.parse(data);
if (returned_data.error) {
console.log('An eror has occoured. details: ' + JSON.stringify(returned_data));
returned_data = '';
}
return JSON.stringify(returned_data);
}
app.post('/api/getuserinfo/tom', function(request, response) {
makeProxyApiRequest('tom', response);
//response.end(result);
});
var port = 7331;
proxy_query.js:
var https = require('https');
var callback = undefined;
var options = {
host: 'targetsite.com',
port: 443,
method: 'GET',
};
function resultHandlerCallback(result) {
var buffer = '';
result.setEncoding('utf8');
result.on('data', function(chunk){
buffer += chunk;
});
result.on('end', function(){
if (callback) {
callback(buffer);
}
});
}
exports.getUserData = function(name, user_callback) {
callback = user_callback
options['path'] = user + '?name=' + name;
var request = https.get(options, resultHandlerCallback);
request.on('error', function(e){
console.log('error from proxy_query:getUserData: ' + e.message)
});
request.end();
}
app.listen(port);
I wish I didn't screwed this code because I replaced some stuff to fit my example.
Anyway, the problem is that I want to post the response to the user when the HTTP request is done and I cant find how to do so because I use express and express uses asynchronous calls and so do the http request.
I know that if I want to do so, I should pass the makeProxyApiRequest the response object so he would be able to pass it to the callback but it is not possible because of asyn problems.
any suggestions?
help will be appreciated.
As you're using your functions to process requests inside your route handling, it's better to write them as express middleware functions, taking the specific request/response pair, and making use of express's next cascade model:
function makeProxyApiRequest(req, res, next) {
var name = parseProxyApiRequest(req.name);
res.locals.userdata = proxy.getUserData(name);
next();
}
function parseProxyApiRequest(req, res, next) {
try {
// remember that JSON.parse will throw if it fails!
data = JSON.parse(res.locals.userdata);
if (data .error) {
next('An eror has occoured. details: ' + JSON.stringify(data));
}
res.locals.proxyData = data;
next();
}
catch (e) { next("could not parse user data JSON."); }
}
app.post('/api/getuserinfo/tom',
makeProxyApiRequest,
parseProxyApiRequest,
function(req, res) {
// res.write or res.json or res.render or
// something, with this specific request's
// data that we stored in res.locals.proxyData
}
);
Even better would be to move those middleware functions into their own file now, so you can simply do:
var middleware = require("./lib/proxy_middleware");
app.post('/api/getuserinfo/tom',
middleware.makeProxyApiRequest,
middleware.parseProxyApiRequest,
function(req, res) {
// res.write or res.json or res.render or
// something, with this specific request's
// data that we stored in res.locals.proxyData
}
);
And keep your app.js as small as possible. Note that the client's browser will simply wait for a response by express, which happens once res.write, res.json or res.render etc is used. Until then the connection is simply kept open between the browser and the server, so if your middleware calls take a long time, that's fine - the browser will happily wait a long time for a response to get sent back, and will be doing other things in the mean time.
Now, in order to get the name, we can use express's parameter construct:
app.param("name", function(req, res, next, value) {
req.params.name = value;
// do something if we need to here, like verify it's a legal name, etc.
// for instance:
var isvalidname = validator.checkValidName(name);
if(!isvalidname) { return next("Username not valid"); }
next();
});
...
app.post("/api/getuserinfo/:name", ..., ..., ...);
Using this system, the :name part of any route will be treated based on the name parameter we defined using app.param. Note that we don't need to define this more than once: we can do the following and it'll all just work:
app.post("/api/getuserinfo/:name", ..., ..., ...);
app.post("/register/:name", ..., ..., ... );
app.get("/api/account/:name", ..., ..., ... );
and for every route with :name, the code for the "name" parameter handler will kick in.
As for the proxy_query.js file, rewriting this to a proper module is probably safer than using individual exports:
// let's not do more work than we need: http://npmjs.org/package/request
// is way easier than rolling our own URL fetcher. In Node.js the idea is
// to write as little as possible, relying on npmjs.org to find you all
// the components that you need to glue together. If you're writing more
// than just the glue, you're *probably* doing more than you need to.
var request = require("request");
module.exports = {
getURL: function(name, url, callback) {
request.get(url, function(err, result) {
if(err) return callback(err);
// do whatever processing you need to do to result:
var processedResult = ....
callback(false, processedResult);
});
}
};
and then we can use that as proxy = require("./lib/proxy_query"); in the middleware we need to actually do the URL data fetching.

Require in nodejs

The argument of require(...) in node.js is a filename. If I had a module source code in a string code, could I somehow call require(code) and load functions from that string?
I put this into a function for reuse. It creates a file in the os temp directory based on a random hash, requires it and then deletes it.
var fs = require('fs'),
os = require('os'),
crypto = require('crypto');
function requireString(moduleString) {
var token = crypto.randomBytes(20).toString('hex'),
filename = os.tmpdir() + '/' + token + '.js',
requiredModule = false;
// write, require, delete
fs.writeFileSync(filename, moduleString);
requiredModule = require(filename);
fs.unlinkSync(filename);
return requiredModule;
}
Then you can do:
var carString = "exports.start = function(){ console.log('start'); };",
car = requireString(carString);
console.log("Car:", car);
This is still more of a workaround, but more convenient to use, I think.
A work around could be to write the module source code to a temporary file ./tmp-file.js and then require('./tmp-file'), and then remove the file.
This is probably not optimal because you would either have to block and write the file synchronously, or put everything requiring that module in the callback to the async write.
A working example for async file write (gist - also includes sync file write):
var http = require('http');
var fs = require('fs');
var helloModuleString = "exports.world = function() { return 'Hello World\\n'; }";
fs.writeFile('./hello.js', helloModuleString, function (err) {
if (err) return console.log(err);
var hello = require('./hello');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(hello.world());
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
});
Results in:
$ curl 127.0.0.1:1337
> Hello World

Categories