node can't set headers after they are sent - javascript

i know this question asked many time before but still i'm struggling to figure this out. i have a set of js files. first one is index.js
app.all('/backend/*/*', function(req, res){ // backend/product/getProduct
serviceType = req.params[0];
methodType = req.params[1];
exports.serviceType= serviceType;
exports.methodType= methodType;
main.checkService()
});
in here im extracting the params and call checkService method in main.js file
main.js
function checkService(){
switch(index.serviceType){
case 'product':
product.checkMethod();
break;
default :
console.log('no such service')
}
}
then it move to product.js file
function checkMethod(){
var methodName = index.methodType,
res = index.res,
req = index.req;
switch(methodName){
case 'samplePost':
var body = req.body;
proHan.samplePost(body,function(data,msg,status){
sendRes(data,msg,status);
});
break;
default :
console.log('no such method')
}
function sendRes(jsonObj,msg,status){
var resObj = {
status : status,
result : jsonObj,
message : msg
}
res.json(resObj);
}
first it moves to samplePost method in handler.js
once the http req finised executing, callback return the results and call sendRes method and send the json
function samplePost(jsonString,cb){
var res = config.setClient('nodeSample');
// jsonString = JSON.parse(jsonString);
res.byKeyField('name').sendPost(jsonString,function(data,msg,status){
cb(data,msg,status);
});
}
to send http req i written a common file. that is config.js
function setClient(_cls){
var client = new Client(url);
return client;
}
function parentClient(url){
this.postBody = {
"Object":{},
"Parameters":{
"KeyProperty":""
}
};
}
function paramChild(){
parentClient.apply( this, arguments );
this.byKeyField = function(_key){
this.postBody.Parameters.KeyProperty = _key;
return this;
}
}
function Client(url){
parentClient.apply( this, arguments );
this.sendPost = function(_body,cb){
_body = (_body) || {};
this.postBody.Object = _body;
var options = {
host : 'www.sample.com',
port : 3300,
path: '/somrthing',
headers: {
'securityToken' : '123'
}
};
options.method = "POST";
var req = http.request(options, function(response){
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
cb(JSON.parse('[]'),'success',200)
});
});
//This is the data we are posting, it needs to be a string or a buffer
req.on('error', function(response) {
cb(JSON.parse('[]'),response.errno,response.code)
});
req.write(JSON.stringify(this.postBody));
req.end();
}
}
paramChild.prototype = new parentClient();
Client.prototype = new paramChild();
when i send the first req its work but from then again the server crashes. it seems like i can't call res.end method again in a callback method. how can i fix this. thank you.

you can't call res.end two times. Here is a simple exemple to deal with callback with a basic node server.
const http = require('http');
const hostname = '127.0.0.1';
const port = 4242;
let something = true;
function callback(req, res) {
something = !something;
res.setHeader('Content-Type', 'text/plain');
res.end('Callback Hello World\n');
}
const server = http.createServer((req, res) => {
res.statusCode = 200;
if (something) {
callback(req, res);
} else {
something = !something;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
}
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});

Related

My weather app is throwing type error of temp.. It was console logging the data when I checked but as I enter city Lat and Log it shows type error [duplicate]

I'm trying to get my function to return the http get request, however, whatever I do it seems to get lost in the ?scope?. I'm quit new to Node.js so any help would be appreciated
function getData(){
var http = require('http');
var str = '';
var options = {
host: 'www.random.org',
path: '/integers/?num=1&min=1&max=10&col=1&base=10&format=plain&rnd=new'
};
callback = function(response) {
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
});
//return str;
}
var req = http.request(options, callback).end();
// These just return undefined and empty
console.log(req.data);
console.log(str);
}
Of course your logs return undefined : you log before the request is done. The problem isn't scope but asynchronicity.
http.request is asynchronous, that's why it takes a callback as parameter. Do what you have to do in the callback (the one you pass to response.end):
callback = function(response) {
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(req.data);
console.log(str);
// your code here if you want to use the results !
});
}
var req = http.request(options, callback).end();
Simple Working Example of Http request using node.
const http = require('https')
httprequest().then((data) => {
const response = {
statusCode: 200,
body: JSON.stringify(data),
};
return response;
});
function httprequest() {
return new Promise((resolve, reject) => {
const options = {
host: 'jsonplaceholder.typicode.com',
path: '/todos',
port: 443,
method: 'GET'
};
const req = http.request(options, (res) => {
if (res.statusCode < 200 || res.statusCode >= 300) {
return reject(new Error('statusCode=' + res.statusCode));
}
var body = [];
res.on('data', function(chunk) {
body.push(chunk);
});
res.on('end', function() {
try {
body = JSON.parse(Buffer.concat(body).toString());
} catch(e) {
reject(e);
}
resolve(body);
});
});
req.on('error', (e) => {
reject(e.message);
});
// send the request
req.end();
});
}
Shorter example using http.get:
require('http').get('http://httpbin.org/ip', (res) => {
res.setEncoding('utf8');
res.on('data', function (body) {
console.log(body);
});
});
from learnyounode:
var http = require('http')
http.get(options, function (response) {
response.setEncoding('utf8')
response.on('data', console.log)
response.on('error', console.error)
})
'options' is the host/path variable
from learnyounode:
var http = require('http')
var bl = require('bl')
http.get(process.argv[2], function (response) {
response.pipe(bl(function (err, data) {
if (err)
return console.error(err)
data = data.toString()
console.log(data)
}))
})
I think it's too late to answer this question but I faced the same problem recently my use case was to call the paginated JSON API and get all the data from each pagination and append it to a single array.
const https = require('https');
const apiUrl = "https://example.com/api/movies/search/?Title=";
let finaldata = [];
let someCallBack = function(data){
finaldata.push(...data);
console.log(finaldata);
};
const getData = function (substr, pageNo=1, someCallBack) {
let actualUrl = apiUrl + `${substr}&page=${pageNo}`;
let mydata = []
https.get(actualUrl, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', async () => {
if (JSON.parse(data).total_pages!==null){
pageNo+=1;
somCallBack(JSON.parse(data).data);
await getData(substr, pageNo, someCallBack);
}
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}
getData("spiderman", pageNo=1, someCallBack);
Like #ackuser mentioned we can use other module but In my use case I had to use the node https. Hoping this will help others.
This is my solution, although for sure you can use a lot of modules that give you the object as a promise or similar. Anyway, you were missing another callback
function getData(callbackData){
var http = require('http');
var str = '';
var options = {
host: 'www.random.org',
path: '/integers/?num=1&min=1&max=10&col=1&base=10&format=plain&rnd=new'
};
callback = function(response) {
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
callbackData(str);
});
//return str;
}
var req = http.request(options, callback).end();
// These just return undefined and empty
console.log(req.data);
console.log(str);
}
somewhere else
getData(function(data){
// YOUR CODE HERE!!!
})

How to pull string from javascript file with promises?

I have a node.js app that has a few files that I am working with, but the main two javascript files are a RestController and AuthController. The RestController is supposed to call the AuthController to pull a new access token from Salesforce, the server that I am attempting to hit.
I currently set up my AuthController.js to work with promises so that I can wait to get my access token. The problem is I have no idea how to get my RestController.js file to wait for the access token from the AuthController.js file.
I am also very very new to Javascript and Promises, so I am not sure if I even set up my functions correctly. Basically, I want my AuthController to handle getting the access token and the RestController to handle the Rest request to our server.
AuthController.js
var fs = require('fs');
var jwt = require('jsonwebtoken');
var request = require('request');
var querystring = require('querystring');
var config = require('../../configs/config.json');
var filename = __dirname + '/../../' + config.key_path;
var access_token;
var readFilePromise = function(file) {
return new Promise(function(ok, notOk) {
fs.readFile(file, function(err,data) {
if (err) {
notOk(err);
} else {
ok(data);
}
});
});
}
var getAccessToken = function(key) {
return new Promise(function(ok,notOk) {
var jwtparams = {
iss : config.client_id,
sub: config.username,
aud: 'https://' + config.host,
exp : Date.now() + 300
};
var token = jwt.sign(jwtparams, key, {algorithm: 'RS256'});
var data = querystring.stringify({
grant_type : 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion : token
});
request.post({
headers: {
'Content-Type' : 'application/x-www-form-urlencoded',
'Content-Length' : data.length
},
url: 'https://' + config.host + '/services/oauth2/token',
body: data
}, function(error, response, body) {
if (error) {
return notOk(error);
}
try {
ok(JSON.parse(body).access_token);
} catch (e) {
notOk(e);
}
});
});
}
function main() {
readFilePromise(filename).then(function(data) {
getAccessToken(data.toString()).then(function(data) {
access_token = data.toString();
});
});
}
module.exports = {main};
RestController.js
var https = require('https');
var request = require('request');
var auth = require('./authController.js');
class SystemController {
doProcessPostStatus (req,res) {
if (!req.body.systemId) {
return res.status(400).send([
{
'errorCode' : 'INVALID_REQUEST_BODY',
'message' : 'System Id "systemId" variable is required.'
}
]);
} else if (typeof req.body.success === 'undefined') {
return res.status(400).send([
{
'errorCode' : 'INVALID_REQUEST_BODY',
'message' : 'Success "success" variable is required'
}
]);
} else if (!req.body.message) {
return res.status(400).send([
{
'errorCode' : 'INVALID_REQUEST_BODY',
'message' : 'Message "message" variable is required'
}
]);
}
var access_token = auth.main();
console.log(access_token);
}
}
var systemControllerVar = new SystemController();
module.exports = systemControllerVar;
Any help is greatly appreciated as I am currently stuck, thanks!

Response.write doesn't display variable string

So, I'm learning node, tried to write simple server by my self. When it comes to write data to response, it doesn't work properly. I converted data to String, i tried to display data to the console and it had benn displayed normally, but when I pass it to response.write() nothing changes at my page. I created file called 'lorem' in poems/lorem directory, I write this path to my link in browser.
As you can see, I was writting some debugging stuff, but I deleted most of it.
var http = require('http');
var fs = require('fs');
var path = require('path');
var port = process.argv[2];
var readFileContent = (filePath) =>
{
var readData = '';
fs.readFile(path.normalize(process.cwd() + filePath), 'utf-8', (err, data) =>
{
let invalid = false;
if(err || data === undefined)
{
invalid = true;
}
if(!invalid) readData = data;
console.log(readData); // logs data from a file
});
return readData;
}
var serverHandler = (request, response) =>
{
let responseData = readFileContent(request.url);
if(responseData != undefined)
{
response.writeHead(200, {'Content-Type':'text/html'});
response.write(''+ responseData.toString()); // there is a problem: writes data only when I pass some exact string (e.g. 'LOREM')
}
else{
response.writeHead(404);
response.write('Error occured');
}
response.end(responseData.toString());
}
http.createServer(serverHandler).listen(+ port);
console.log('Server is lisntening on port ' + port);
There some console output for 'C:/folderpath/ node server.js 8080' cmd:
Server is lisntening on port 8080
lorem
lorem
lorem
Content of 'poems/lorem' file == 'lorem'
I think your problem is with asynchronicity.
Provide your file reading function with a callback, which returns the file content.
Like this:
var readFileContent = (filePath, callback) =>
{
fs.readFile(path.normalize(process.cwd() + filePath), 'utf-8', (err, data) =>
{
let invalid = false;
if(err || data === undefined)
{
invalid = true;
}
if(!invalid) readData = data;
callback(readData)
});
}
And in your server handler function do the following:
var serverHandler = (request, response) =>
{
readFileContent(request.url, (responseData) => {
if(responseData != undefined) {
response.writeHead(200, {'Content-Type':'text/html'});
response.write(''+ responseData.toString());
}
else {
response.writeHead(404);
response.write('Error occured');
}
response.end(responseData.toString());
});
}

Callback is not a function -manage asynchronous call Node js

I am reading files from ftp using the code below.
var JSFtp = require("jsftp");
var config = require('./config.json');
var FtpService = function () {};
// Connect to FTP
var Ftp = new JSFtp({
host: config.ftp.host,
port: config.ftp.port,
user: config.ftp.user,
pass: config.ftp.pass
});
FtpService.prototype.getFTPDirectoryFiles = function (callback) {
Ftp.list(config.ftp.FilePath, function(err, res) {
if(err){
console.log('File Listing Failed', err);
callback(null,err);
return;
}
else{
console.log(res);
callback(null,res);
}
});
};
FtpService.prototype.closeFtp = function () {
console.log('Disconnect to FTP');
};
module.exports = new FtpService();
Now i include this ftp service js file in my index.js as
var ftp = require('./ftpservice.js');
ftpfiles = ftp.getFTPDirectoryFiles();
console.log(ftpfiles);
getFTPDirectoryFiles returns the list of file. But if i call it via index.js i get undefined ftpfiles. This is because of the asynchronous nature of node js.
so i thought of adding callback but
I am getting the error Callback is not defined in function FtpService.prototype.getFTPDirectoryFiles
In this line:
ftpfiles = ftp.getFTPDirectoryFiles()
you are not passing the callback that that function requires and are trying to use a return value that the function does not return.
You need to do something like this:
var ftp = require('./ftpservice.js');
ftp.getFTPDirectoryFiles(function(err, ftpfiles) {
if (err) {
console.log(err);
} else {
console.log(ftpfiles);
}
});
You need to pass a callbackfunction in your function getFTPDirectoryFiles();
var ftp = require('./ftpservice.js');
var ftpFiles;
function setFtpFiles(err, res) {
if (err) throw err;
ftpFiles = res; // to use "ftpFiles" variable later
console.log(res);
}
ftp.getFTPDirectoryFiles(setFtpFiles);
1 Don't change args order to call callback. (replace callback(null,err); and callback(null,res); by callback(err,res);)
2 You need define a specifc function (your callaback) an give it to ftp.getFTPDirectoryFiles().
var JSFtp = require("jsftp");
var config = require('./config.json');
var FtpService = function () {};
// Connect to FTP
var Ftp = new JSFtp({
host: config.ftp.host,
port: config.ftp.port,
user: config.ftp.user,
pass: config.ftp.pass
});
FtpService.prototype.getFTPDirectoryFiles = function (callback) {
Ftp.list(config.ftp.FilePath, function(err, res) {
if(err){
console.log('File Listing Failed', err);
callback(err, res);
return;
}
else{
console.log(res);
callback(err, res);
}
});
};
FtpService.prototype.getFTPDirectoryFilesSimplify = function (callback) {
// no console.log, but very more simple !
Ftp.list(config.ftp.FilePath, callback);
};
FtpService.prototype.closeFtp = function () {
console.log('Disconnect to FTP');
};
and then :
var ftp = require('./ftpservice.js');
ftpfiles = ftp.getFTPDirectoryFiles(function(err,res){
// do your specifc job here using err and res
});
console.log(ftpfiles);

Node js not working after update

After I updated to 6.9.2 from 4.4.0, my node.js file is crashing on client disconnect with something like:
this.ee._events.hasOwnProperty undefined at ultron\index.js:80 at process._tickCallback (internal/process/next_tick.js:98:9)
If I rollback to 4.4.0, it works correctly again. I am running this from nodemon server on Windows OS.
var server = require('http').createServer();
var io = require('socket.io')(server);
var http = require('http');
var querystring = require('qs');
io.on('connection', function(client){
var host = client.request.headers.host.split(':');
client.host = host[0];
console.log('new connection');
client.on('call', function(socketData){
if(socketData == "undefined" || !socketData.controller) {
return;
}
var path = stripHostFromPath(client.host, socketData.controller);
requestData(client.host, path, client.request.headers.cookie, 'GET',
function (body) {
var controllerSlices = socketData.controller.split('/');
var controller = controllerSlices[controllerSlices.length -1].replace('?', "");
var controllerObj = querystring.parse(controller);
var data = IsJsonString(body);//return json if true
if (controllerObj && controllerObj.f == 'updateUser') {
if (data != false) {
client.user_id = data.userId;
io.sockets.sockets['user_id'] = client.user_id;
}
}
if (data != false) {
if (data.broadcast) {
for (var i=0;i<data.broadcast.length;i++) {
//check if the user is connected
for (var k=0;k<io.sockets.sockets.length;k++) {
if (io.sockets.sockets[k]['user_id'] == data.broadcast[i]) {
io.sockets.sockets[k].emit(data.broadcastEvent, data.broadcastData);
}
}
}
}
}
});
});
client.on('disconnect', function(){
console.log('client disconected');
});
});
console.log('server listed on port 3000');
server.listen(3000);
function requestData(host, path, cookie, method, callbacks, postData) {
if (!method) method = 'POST';
if (!cookie) cookie = '';
var options = {
host: host,
port: '80',
path: path,
method: method,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': cookie
}
};
if (postData) {
postData = querystring.stringify( JSON.parse(postData) );
options.headers['Content-Length'] = Buffer.byteLength(postData);
}
try {
var req = http.request(options, function (res) {
// response is here
//console.log(res.statusCode);
//check if request was ok.
var body = '';
res.setEncoding('utf8');
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function () {
callbacks(body);
});
res.on('error', function(e){
console.log(e);
});
});
if (postData) {
req.write(postData);
}
req.end();
}
catch(e) {
console.log('requestData error:');
console.log(e);
}
}
It sounds like you have an older version of socket.io installed. By upgrading to the latest version, that should update engine.io which will update ws which will update its ultron dependency to 1.0.2, where the issue is fixed.

Categories