formidable parse callback not be called and no error - node.js

I have problem when I use formidable parse function. In my project, I use httpsys (not build-in http module) to create server (for port sharing), and then I send a post request with multipart form data(including string and zip file). Then I want to use formidable to parse request body. But parse function callback does not be called. There is no error. I do not use Express application, but I use Express Router to route my requests. I already use error handler to catch error, but it never be called (form.on('error', function(err) { console.log(err); });). Anyone has same problem? Please help me out, thanks in advance.
// main.js
var router = express.Router();
router.use(function (req, res, next) {
for (var i in req.headers) {
req.headers[i] = querystring.unescape(req.headers[i]);
req.headers[i] = req.headers[i].replace(/\+/g, "");
}
next();
});
//router.use(bodyParser());
router.post('/TestServer/' + 'TestRequest', function(req, res) {
testRequestHandler.execute(req, res);
});
var server = require('httpsys').http().createServer(router);
var port = '80'; // or other port
var listeningPort = 'http://localhost:' + port + '/TestServer/';
server.listen(listeningPort );
// In testRequestHandler
var execute = function(req, res) {
var form = new Formidable.IncomingForm();
form.uploadDir = uploadDir.getPath();
form.encoding = Constants.ENCODING_UTF8;
form.on('file', function(name, file) {console.log('file='+file);});
form.on('error', function(err) { console.log(err); }); // never be called
form.on('aborted', function() { console.log('Aborted'); });
form.parse(req, function(err, fields, files) {
//todo test code
console.log( "parse finished" );
});
}

Related

logging all request and data in server file node.js

I have to build a custom logger that logs information about each request it receives. I have to use: Agent,Time,Method,Resource,Version,Status I think I already created my logger and the things i want to to log. now i have to Expose an endpoint http://localhost:3000/logs that will return a json object with all the logs I dont know how to do it. Help!
const express = require('express');
const fs = require('fs');
const app = express();
app.use(( req, res, next) => {
// write your logging code here
var agent = req.headers('user-agent');
var time = new Date()
var method = req.method;
var baseUrl = req.originalUrl;
var version = 'HTTP/' + req.httpVersion;
var status = res.statusCode;
var allData = agent + time + method + baseUrl + version + status;
fs.appendFile('./log.csv', allData, (err) => {
if (err) throw err;
console.log(allData)
next()
})
});
app.get('/', (req, res) => {
// write your code to respond "ok" here
res.status(200).send('Ok');
});
app.get('/logs', (req, res) => {
// write your code to return a json object containing the log data here
fs.readFile('log.csv', 'utf8', (err, data) => {
});
module.exports = app;
}
Check this library. You can use it for csvtojson conversion.
Anyway, consider that if the csv file dimensions grows a lot, reading the whole file and converting it to JSON will be an overkill. Consider a database for a scalable solution.

Express: Can't set headers after they are sent

Following is my server file. I am making 2 calls, one post and one get. It works fine at times. But gives an error of : Can't set headers after they are sent. Does this have anything to do with my client side code?
server.js
var express = require('express')
var mongoose = require('mongoose')
var path = require('path')
var bodyParser = require("body-parser")
var cors = require("cors")
var app = express()
var port = process.env.PORT || 3000
var Url = require("./data/url-schema");
//Express request pipeline
app.use(express.static(path.join(__dirname,"../client")))
app.use(bodyParser.json())
app.use(cors());
/*
Your server must be ready to handle real URLs. When the app first loads at / it will probably work, but as the user navigates around and then hits refresh at /dashboard your web server will get a request to /dashboard. You will need it to handle that URL and include your JavaScript application in the response.
*/
app.get('*', function (request, response, next){
response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
next()
})
app.get('/:code', function(req, res) {
console.log("reg", req.params.code)
Url.findOne({code:req.params.code}, function(err, data){
console.log("data", data)
if(data)
res.redirect(302, data.longUrl)
else
res.end()
})
})
app.post('/addUrl', function (req, res, next) {
console.log("on create");
Url.findOne({longUrl:req.body.longUrl}, function(err, data) {
if (err)
res.send(err);
else if(data) {
console.log("already exists",data)
res.send("http://localhost:3000/"+data.code);
} else {
var url = new Url({
code : Utility.randomString(6,"abcdefghijklm"),
longUrl : req.body.longUrl
});
console.log("in last else data created",url)
url.save(function (err, data) {
console.log(data)
if (err)
res.send(err);
else
res.send("http://localhost:3000/"+data.code);
});
}
});
})
app.listen(port, function () {
console.log('Example app listening on port 3000!')
});
// Connect to our mongo database
mongoose.connect('mongodb://localhost/shortUrl');
I get the Following error
error
_http_outgoing.js:335
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.header (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:718:10)
at ServerResponse.location (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:835:8)
at ServerResponse.redirect (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:874:8)
at Query.<anonymous> (/opt/lampp/htdocs/url-shortener/server/server.js:30:8)
at /opt/lampp/htdocs/url-shortener/node_modules/mongoose/node_modules/kareem/index.js:177:19
at /opt/lampp/htdocs/url-shortener/node_modules/mongoose/node_modules/kareem/index.js:109:16
at process._tickCallback (node.js:355:11)
From the execution order, in * route handler, the body is being assigned to the response and then in /:code, the response code 302 is being added, where Location header is also added, hence the error. Any header must be added before the body to the response.
To solve this problem, simply change the order of the two GET statements.
Finally found the solution:
var express = require('express')
var mongoose = require('mongoose')
var path = require('path')
var bodyParser = require("body-parser")
var app = express()
var port = process.env.PORT || 3000
var Url = require("./data/url-schema")
var Utility = require("./utility")
//Express request pipeline
app.use(express.static(path.join(__dirname,"../client")))
app.use(bodyParser.json())
/*
Your server must be ready to handle real URLs. When the app first loads at / it will probably work, but as the user navigates around and then hits refresh at /dashboard your web server will get a request to /dashboard. You will need it to handle that URL and include your JavaScript application in the response.
*/
app.get('/dashboard', function (request, response, next){
response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
next()
})
app.get('/about', function (request, response, next){
response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
next()
})
app.get('/:code', function(req, res) {
Url.findOne({code:req.params.code}, function(err, data){
if(data){
res.redirect(302, data.longUrl)
}
})
})
app.post('/addUrl', function (req, res, next) {
Url.findOne({longUrl:req.body.longUrl}, function(err, data) {
if (err){
res.send(err)
}
else if(data) {
res.send("http://localhost:3000/"+data.code);
} else {
var newCode = getCode()
checkCode(newCode)
.then(function(data){
var url = new Url({
code : data,
longUrl : req.body.longUrl
});
url.save(function (err, data) {
if (err)
res.send(err);
else
res.send("http://localhost:3000/"+data.code);
});
})
}
});
})
app.listen(port, function () {
console.log('Example app listening on port 3000!')
});
// Connect to our mongo database
mongoose.connect('mongodb://localhost/shortUrl');
//Generate a random code
function getCode() {
return Utility.randomString(6,"abcdefghijklmnopqrstuvwxyz")
}
//Check if the code is unique
function checkCode(code) {
return new Promise(function (resolve, reject){
Url.findOne({code:code}, function(err, data) {
if(err === null){
resolve(code)
}else if(data){
saveUrlCode(getCode())
}
})
})
}
My earlier route which was :
app.get('*', function (request, response, next){
response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
next()
})
The get route was getting executed twice on account of the above call and the
app.get(":/code") call.
So I had to handle the routes properly which I have done by handling the dashboard and about routes separately instead of using the "*" route.

Express & connect-busboy ignore from some requests

I use connect-busboy with express:
var busboy = require('connect-busboy');
app.configure(function () {
app.use(express.logger());
app.use(busboy());
app.use(bodyParser());
app.use(function(err, req, res, next){
res.send(500, 'error');
});
and with the following request:
app.post('/save', function (req, res) {
console.log("Got request")
try {
console.log("I got it");
req.pipe(req.busboy);
var name = "";
var start = "";
var fstream;
req.busboy.on('field', function (fieldname, val, fieldnameTruncated, valTruncated) { }
req.busboy.on('file', function (fieldname, file) {
//some code
}
req.busboy.on('error', function (error) {
console.log("Error in uploading file with chunks: " + error);
// some code
})
req.busboy.on('finish', function () {
fstream.on('close', function(){
//some code
})
})
the client send me 6 request for save command. I get inconsistently 2-6 requests.
Meaning, Got request is printed only 2 times, but the client send 6 times the request.
When I delete the app.use(busboy()); line, Express.app get the 6 request (but I can't use the function because the req.busboy.on doesn't work).
The conclusion is that app.use(busboy()); ignore some requests from the client, and the app.post isn't fired. How can I solve it?
One thing you should do is remove app.use(bodyParser()); because busboy is already handling body parsing.

How do I get POST data with node.js?

How do I get the caller ID from twilio? I've tried many different ways to get the POST data but it isn't working.
var twilio = require('./node_modules/twilio/index'),
http = require('http'),
express = require('express');
http.createServer(function (req, res) {
/*
var app = express();
app.use(express.urlencoded());
app.post('/call',function (req, res) {
*/
var name, from;
// if (req.method=='POST')
// req.on('From', function (data) {from = data;});
try {
from = req.param('From');
// from = req.body.from;
}
catch (err)
{
console.log("No Caller ID");
}
console.log("Number: " + from);
//Some code goes here..
res.end(resp.toString());
}).listen(8080);
It's throwing me the error every single time at the try catch statement (always null).
I'm trying to get the caller ID of an incoming text message.
Things in comments are the different approaches I tried.
The thrown error is:
Error TypeError: Object #IncomingMessage> has no method 'param'
I guess that this will do the trick:
var qs = require('querystring');
var processRequest = function(req, callback) {
var body = '';
req.on('data', function (data) {
body += data;
});
req.on('end', function () {
callback(qs.parse(body));
});
}
var http = require('http');
http.createServer(function (req, res) {
processRequest(req, function(data) {
// data
});
}).listen(9000, "127.0.0.1");

moving a simple uploaded file to a new location

What i am trying to do ::
I am trying to move the uploaded file to /public/images
My request::
My app.js code
var express=require('express');
var mysql=require('mysql');
var fs=require('fs');
var http=require('http');
var crypto=require('crypto');
var app=express();
var connection=mysql.createConnection({
host:'localhost',
user:'******',
password:'******',
database:'*********'
});
connection.connect();
app.set('port',process.env.PORT||7002);
app.use(express.bodyParser());
app.post('/Details/',function(req,res){
var file_name=req.files.key.originalFilename;
console.log(file_name);
crypto.randomBytes(8, function(ex, buf) {
var array = req.files.key.originalFilename.split('.');
var type = array[array.length - 1];
var name = buf.toString('hex') + '.' + type;
fs.rename(req.files.key.path, './public/images/' + name, function(e) {
next(e, name);
});
});
});
http.createServer(app).listen(app.get('port'),function(){
console.log('Express server listening on port'+app.get('port'));
});
Error i am facing::
next(e, name)......... "next" not defined
How to resolve this ?
What exactly do you want to do? I think that instead of calling next, you want to generate a response back to the client.
So instead of this:
next(e, name);
Do this:
if (e) {
res.send(500, e.message);
} else {
res.send(WHATEVER_YOU_WANT_TO_SEND_AS_RESPONSE);
}
If you really want to call next, you need to add it to the callback function's argument list:
app.post('/Details/', function(req, res, next) { ...

Resources