NodeJS/Express GET exit status of external application - node.js

I am pretty new to NodeJS and this is my first time with Express 4, I'm trying to build a simple RESTful front-end around a command-line application. There will ultimately only be one GET and one POST necessary, with the POST handling about 3 or 4 different parameters. The GET should call the command-line application with all default parameters, which is basically just a status check and return the exit status upon completion. The POST will pass along POST parameters on the commandline. I know that this basically calls for an asynchronous call, like child_process.execFile(), but I can't seem to figure out how to actually return the response from within the callback function.
This is the tutorial I used as a starting point, omitting the mongoose dependency, because I have no need for MongoDB, so I basically just followed it up to the point where you start the server. At this point, I'm pretty lost. I always hate writing async code...
var express = require('express'); // call express
var app = express(); // define our app using express
var bodyParser = require('body-parser');
var child_process = require('child_process');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var port = process.env.PORT || 8080; // set our port
var router = express.Router(); // get an instance of the express Router
router.get('/', function(req, res) {
res.json({ message: 'hooray! welcome to our api!' });
});
router.get('/myapp/status', function(req, res) {
console.log(req.user);
child_process.execFile(
'casperjs',
['myfile.js', '--cmd="Status"', '--user="myuser"', '--pass="#mypass"'],
null,
function(response) {
// ???
}, res);
});
app.use('/api', router);
app.listen(port);
console.log('Magic happens on port ' + port);

You can try the following:
router.get('/myapp/status', function(req, res) {
console.log(req.user);
child_process.execFile(
'casperjs', //command
["myfile.js --cmd=Status --user=myuser --pass=#mypass"], // args
function(err, stdout, stderr) { //callback
if (err) {
return res.status(500).send(err);
}
res.send(stdout); // to send response to client
});
});

Related

Read google calendar events

I want to read the events of a public google calendar without Oauth authentication.
But i can't get a response:
const express = require("express");
const bodyParser = require("body-parser");
const request = require("request");
const app = express();
app.use(express.static("public"));
app.use(bodyParser.urlencoded({
extended: true
}));
app.get("/", function(req, res) {
res.sendFile(__dirname + "/index.html");
});
app.post("/", function(req,res){
request("https://www.googleapis.com/calendar/v3/calendars/XXXXXXXXXXXX.calendar.google.com/events",function(response){
var calendarSummary = response.summary;
var calendarDescription =response.description;
console.log("Response is:");
console.log("Result is: "+calendarSummary+calendarDescription);
});
});
app.listen(3000, function() {
console.log("server is running on port 3000");
});
Any suggestions? Do i need to include an API-key for a public calendar?
I think the issue is your usage of the request library/function. Per the docs The signature for that function is request(error, response, body), but you only supply one argument. Despite calling it response, it's actually the error object which is probably null. So, change it to the following and I bet it'll work:
request("https://www.googleapis.com/calendar/v3/calendars/XXXXXXXXXXXX.calendar.google.com/events", function(error, response, body) {
var calendarSummary = body.summary;
var calendarDescription = body.description;
console.log("Response is:");
console.log("Result is: " + calendarSummary + calendarDescription);
});
I think your API call to Google is fine as-is because the documentation says no authorization is needed.

How to prevent routes from being called multiple time in express.js

I am new to node.js and I am trying to make a simple task list app using express.js and express-session. However, for a reason that I don't understand most of the routes are called two or tree times when I make a request and it shouldn't. For instance, if I send a request to /new the new task is sometimes added two (or three) times instead of one and this causes a problem...
I read in other threads that the problem could come from the browser trying to get a favicon, however if I log all incoming request url (console.log(req.url)) on the /new route, the duplicated requests are always /new and not a favicon...
Here is my code :
var express = require('express');
var session = require('express-session');
// Create a new express application instance
var app = express();
// Initialize session
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true,
cookie: {}
}));
// Initialize req.session.tasks if needed
app.use(function (req, res, next) {
if (req.session.tasks === undefined) {
req.session.tasks = [];
}
next();
});
app.get('/', function (req, res) {
res.send(req.session.tasks);
});
// Create a Test Task
app.get('/new', function (req, res) {
console.log(req.url);
req.session.tasks.push("Test Task");
res.redirect('/');
});
app.get('/clear', function (req, res) {
req.session.tasks = [];
res.redirect('/');
})
app.listen(3000, function () {
console.log('Task Server is listening on port 3000!');
});
Do you have a idea of what could be the cause of this problem and how to avoid it ??
Thanks a lot !

How to fetch data in mongoDB to show in localhost (Node.js)

I am working on to do list app using mongoDB and node.js. Basically you type what you want to do then click add. I successfully connected the database but it doesn't show the text that's in the database. It shows only the bullets in the localhost.
Here's the code:
app.get('/', function(req, res) {
db.collection('list').find().toArray(function (err, result) {
console.log(result);
if (err) {return};
console.log(err);
res.render('index.ejs', {list: result})
});
});
app.post('/', function(req, res){
console.log(req.body);
db.collection('list').save(req.body, function(err, result) {
if (err) {return};
console.log(err);
console.log('saved')
res.redirect('/');
})
})
I have validated the code you posted and have revised it slightly with comments.
I hope this helps but it seems that the fault might be in the res.render method that is being used. Please refer to the following code:
// Requires
var express = require('express');
var bodyParser = require('body-parser');
var MongoClient = require('mongodb').MongoClient;
// Instantiation
var app = express();
var mongopath = "mongodb://localhost:27017/BitX";
// Port number the REST api works on
var portnum = 7500;
// MongoDB object
var db = null;
MongoClient.connect(mongopath, function(err,ldb){
db = ldb;
});
// Implement Body Parser
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
// Start the REST service
var server = app.listen(portnum, function() {
var host = server.address().address;
var port = server.address().port;
console.log("Content Provider Service listening at http://%s:%s", host, port);
});
// Default route
app.get('/', function(req, res) {
// Find all items in orders and send back results to a front end
db.collection('orders').find().toArray(function (err, result) {
res.send(result);
// Consider that the rendering engine may not be functioning correctly
// SEE MORE: https://stackoverflow.com/questions/21843840/what-does-res-render-do-and-what-does-the-html-file-look-like
//res.render('index.ejs', {list: result})
});
});
// Accept a post on the root
app.post('/', function(req, res){
//Save into orders
db.collection('orders').save(req.body, function(err, result) {
res.send(true);
//res.redirect('/');
});
});
For additional information on the res.render method please have a look at:
What does "res.render" do, and what does the html file look like?
- if you have not already.
Hope it helps!

Why is res.send being called twice?

I'm working on creating a middleware for an express router that will execute some code for every request and response. Intercepting a request is easy and there are plenty of examples, but I have not found anything for an elegant approach to intercepting a response. After some research, the best I have come up with is to replace the send function of the response object, shown in the following snippet:
const express = require('express');
const app = express();
var router = express.Router();
var port = process.env.PORT || 3000;
router.get('/test', function(req, res) {
res.send({
message: "testing"
});
});
app.use(function(req, res, next){
console.log("INTERCEPT-REQUEST");
const orig_send = res.send;
res.send = function(arg) {
console.log("INTERCEPT-RESPONSE");
orig_send.call(res, arg);
};
next();
});
app.use("/api", router);
app.listen(process.env.PORT || 3000) && console.log("Running");
There's a problem with this approach: for some reason "INTERCEPT-RESPONSE" is printed in the console twice, meaning res.send is being called twice...
I can set a flag on res.locals the first time it's called to avoid processing the response twice, but I am wondering why res.send is being called twice?
Better example
Try this code to see what are the arguments passed to res.send:
const express = require('express');
const app = express();
var router = express.Router();
var port = process.env.PORT || 3000;
router.get('/test', function(req, res) {
console.log('ACTUAL RESPONSE');
res.send({
message: "testing"
});
});
app.use(function(req, res, next){
console.log("INTERCEPT-REQUEST");
const orig_send = res.send;
res.send = function(arg) {
console.log("INTERCEPT-RESPONSE", JSON.stringify(arguments));
orig_send.call(res, arg);
};
next();
});
app.use("/api", router);
app.listen(process.env.PORT || 3000, function () {
console.log("Running");
});
(I also changed the printing of "Running" to print it when the server is actually listening - your code && was printed before the server was listening - but that's not that important here).
Now after running:
curl http://localhost:3000/api/test
the output on the server console is:
Running
INTERCEPT-REQUEST
ACTUAL RESPONSE
INTERCEPT-RESPONSE {"0":{"message":"testing"}}
INTERCEPT-RESPONSE {"0":"{\"message\":\"testing\"}"}
What happens
As you can see your handler is actually called once by your code, with an object as the first (and only) argument. But then it is called once again with an object serialized to JSON. This is how res.send internally works - see below for details. Since you put your intercepting function on the actual response object then I guess it is calling itself with JSON argument and it doesn't even know that it calls your function in the meantime.
How to avoid it
Try it with the object serialized to JSON by yourself:
const express = require('express');
const app = express();
var router = express.Router();
var port = process.env.PORT || 3000;
router.get('/test', function(req, res) {
console.log('ACTUAL RESPONSE');
res.send(JSON.stringify({
message: "testing"
}));
});
app.use(function(req, res, next){
console.log("INTERCEPT-REQUEST");
const orig_send = res.send;
res.send = function(arg) {
console.log("INTERCEPT-RESPONSE", JSON.stringify(arguments));
orig_send.call(res, arg);
};
next();
});
app.use("/api", router);
app.listen(process.env.PORT || 3000, function () {
console.log("Running");
});
Now it prints:
Running
INTERCEPT-REQUEST
ACTUAL RESPONSE
INTERCEPT-RESPONSE {"0":"{\"message\":\"testing\"}"}
Calling the res.send only once.
Explanation
Now, this is the code that handles object arguments to res.json:
if (chunk === null) {
chunk = '';
} else if (Buffer.isBuffer(chunk)) {
if (!this.get('Content-Type')) {
this.type('bin');
}
} else {
return this.json(chunk);
}
See: https://github.com/expressjs/express/blob/master/lib/response.js#L144-L154
You get the else branch and it calls this.json() (which is res.json() really) with your argument.
But guess what - res.json() calls res.send() in this line:
return this.send(body);
See: https://github.com/expressjs/express/blob/master/lib/response.js#L250
Which calls your intercepting function (for the second time) before running the real res.send().
So, mystery solved. :)

How to capture (or log) the data of the Response object in Express?

I need to capture de sended data. I know how to set a middleware and capture the request and the response header.
I'm asking for capture the sent data.
I'm trying this:
var express = require('express')
var app = express();
var onFinished = require('on-finished')
app.listen(3000);
function logRes(res){
console.log('* captured response *')
console.log(res._header)
console.log(res.statusCode)
console.log(res.statusMessage)
console.log(res.body) // THIS DOES NOT WORKS!
}
app.use(function(req,res,next){
onFinished(res, function (err, res) {
logRes(res)
})
console.log('= captured request =');
console.log(req.method)
console.log(req.path)
console.log(req.query)
next();
});
app.get('/example',function(req,res){
res.header('Content-Type','text/plain');
res.end('example data');
});
Can any says to me how to look at the sent data in the line with the // THIS DOES NOT WORKS! comment?
You first need to include the third party middleware body-parser:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.listen(3000);
app.use(bodyParser.json({ type: 'application/*+json' }));
app.use(function(req,res,next) {
console.log('= captured request =');
console.log(req.method);
console.log(req.path);
console.log(req.query);
console.log(req.body);
next();
});
app.get('/example',function(req,res) {
res.header('Content-Type','text/plain');
res.end('example data');
});
Check the repo and documentation here.

Resources