Express & connect-busboy ignore from some requests - node.js

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.

Related

How to call an api from another api in expressjs?

I have an api like this:
app.get('/test', (req, res) => {
console.log("this is test");
});
and another api:
app.get('/check', (req, res) => {
//I want to call "test" api without redirect to it.
});
I want to call "test" api in "check" api without redirect to "test" api, just do the function in the "test" api.
Above is the example code. 'Cause I dont' want to rewrite function from "test" api to "check"
Simple solution is to define a method which can be called using both request routes.
app.get('/test', (req, res) => {
console.log("this is test");
callMeMayBe();
});
callMeMayBe()
{
//Your code here
}
To "call an API from another API", a quick and easy way is sending HTTP request inside Express server, browser would never know an internal HTTP invocation happens, not mention page-redirect. The benefit of this design includes:
There's no need to change the current API design.
The API invocation can be made exact like sent from browser.
Here is an example:
var http = require('http');
router.get('/test', function(req, res) {
res.end('data_from_test');
});
router.get('/check', function(req, res) {
var request = http.request({
host: 'localhost',
port: 3000,
path: '/test',
method: 'GET',
headers: {
// headers such as "Cookie" can be extracted from req object and sent to /test
}
}, function(response) {
var data = '';
response.setEncoding('utf8');
response.on('data', (chunk) => {
data += chunk;
});
response.on('end', () => {
res.end('check result: ' + data);
});
});
request.end();
});
The result of GET /check would be:
check result: data_from_test
Create a common middleware which need to executed for both the routes.
Below is the code snippet for the same:
app.get('/test', test);
app.get('/check', check, test);
check and test are the middlewares which is used in common.
first define the /test handling function separately.
then you have two options.
// ========( 1 )====== testHandler as another function =============
// you can call this function where ever you want.
var testHandler = function(req, res){
//do something
}
app.get('/test', testHandler);
app.get('/check', function(req, res){
// you can call testHandler function here
testHandler(req, res);
});
// ========( 2 )======= testHandler as a middleware =================
// if you want to call testHandler before running check handler function.
//
var testHandler = function(req, res, next){
//do something
...
next();
}
app.get('/test', testHandler, function(req, res){});
app.get('/check', testHandler, function(req, res){
// you can call testHandler function here
testHandler(req, res);
});

formidable parse callback not be called and no error

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" );
});
}

app.get - is there any difference between res.send vs return res.send

I am new to node and express. I have seen app.get and app.post examples using both "res.send" and "return res.send". Are these the same?
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.type('text/plain');
res.send('i am a beautiful butterfly');
});
or
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.type('text/plain');
return res.send('i am a beautiful butterfly');
});
The return keyword returns from your function, thus ending its execution. This means that any lines of code after it will not be executed.
In some circumstances, you may want to use res.send and then do other stuff.
app.get('/', function(req, res) {
res.send('i am a beautiful butterfly');
console.log("this gets executed");
});
app.get('/', function(req, res) {
return res.send('i am a beautiful butterfly');
console.log("this does NOT get executed");
});
I would like to point out where it exactly made a difference in my code.
I have a middleware which authenticates a token. The code is as follows:
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1] || null;
if(token === null) return res.sendStatus(401); // MARKED 1
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
if(err) return res.sendStatus(403); // MARKED 2
req.user = user;
next();
});
}
On the // MARKED 1 line, if I did not write return, the middleware would proceed and call next() and send out a response with status of 200 instead which was not the intended behaviour.
The same goes for like // MARKED 2
If you do not use return inside those if blocks, make sure you are using the else block where next() gets called.
Hope this helps in understanding the concept and avoiding bugs right from the beginning.
app.get('/', function(req, res) {
res.type('text/plain');
if (someTruthyConditinal) {
return res.send(':)');
}
// The execution will never get here
console.log('Some error might be happening :(');
});
app.get('/', function(req, res) {
res.type('text/plain');
if (someTruthyConditinal) {
res.send(':)');
}
// The execution will get here
console.log('Some error might be happening :(');
});
To Add a little bit more context to the examples above. Express has layers. So if you return in your function you end the execution. If you not end that you can go further in your layered logic.
So the next function passed to each layer can be called to execute the next layer. If you don't call next the execution stops after your method excuted is executed. (Return just exits the function)
The response object is still available after sending. It is just not possible to write to it again because it has already completed after you did res.end() or res.send().
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;
// a controller handles a http request and terminat it
const controller = (req, res, next) => {
// return http response to client
res.send('hello world');
// do something after you sended request
console.log('do something else');
// if you call next the request will go to the next layer -> afterSend,
// if you do not call next the execution will end
next();
};
// this middleware/layer is executed after response is send to client
const afterSend = (req, res, next) => {
// do something after you sended request, but not send again -> readonly
console.log(res);
// this would throw an error
// res.send()
// res.end()
// etc...
};
// we skip routers here
app.get('/hello', controller, afterSend);
app.listen(port, () => {
console.log(`Running on ports ${port}`);
});

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.

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");

Resources