Can't set headers after they are sent in ftp library - javascript

I am using ftp library on npm. I am facing this error
_http_outgoing.js:357
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:357:11)
at ServerResponse.header (/Users/nomanmaqsood/Documents/netsuite-ftp/node_modules/express/lib/response.js:730:10)
First time I get proper response from the library on second call my node app crash due to the above error. Here is my code kindly guide me where is the mistake
c.on ('ready', function () {
c.list (function (err, list) {
if (err) {
c.end();
} else {
if (list.length > 0) {
c.end();
return res.status(200).json({data:list});//crash here on 2nd call
}
}
});
});
please help me out

Check that you don't call res.json or res.send twice on one client http request.
Try
c.on ('ready', function () {
c.list (function (err, list) {
if (err)
return res.status(500).json({error: err.message});
c.end();
res.status(200).json({data: list || []});
});
});
P.S. I suppose that you use Express.

the c was global object, which register itself twice. just make the object local and things works like charm

Related

In nodejs Rest api call, puppeteer page evaluate not returning the response and throws the error

In nodejs Rest api call, puppeteer page evaluate not returning the response and throws the error.
How to return object after executing all the steps, without async
app.get("/api/register", function (req, res) {
res = page.evaluate((res) => {
webex.meetings
.register()
.then(() => {
console.log("Authentication#register() :: successfully registered");
return res.status(200).json({ message: "Successfully Registered" });
})
.catch((error) => {
console.error( "Authentication#register() :: error registering", error);
return res.status(400).json({ message: "Successfully Registered" });
})
}, res);
});
error
:\Users\sansubbu\git\webRTC\node_modules\puppeteer-core\lib\cjs\puppeteer\common\Connection.js:115
const stringifiedMessage = JSON.stringify(Object.assign({}, message, { id }));
^
TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Socket'
| property 'parser' -> object with constructor 'HTTPParser'
--- property 'socket' closes the circle Recursive objects are not allowed.
at JSON.stringify ()
at Connection._rawSend (C:\Users\sansubbu\git\webRTC\node_modules\puppeteer-core\lib\cjs\puppeteer\common\Connection.js:115:41)
at CDPSessionImpl.send (C:\Users\sansubbu\git\webRTC\node_modules\puppeteer-core\lib\cjs\puppeteer\common\Connection.js:320:82)
at ExecutionContext._ExecutionContext_evaluate (C:\Users\sansubbu\git\webRTC\node_modules\puppeteer-core\lib\cjs\puppeteer\common\ExecutionContext.js:211:46)
res is a complex, circular structure that only works in the Node environment. Even if you could, passing it to the browser console via page.evaluate() would take it out of Node, where it belongs, leaving it in an environment where it doesn't make any sense (browsers can't respond to requests as if they were a server).
Instead, try returning a boolean and branching on that on the Node side, where req/res are in their natural environment:
app.get("/api/register", async (req, res) => {
const success = await page.evaluate(async () => {
try {
await webex.meetings.register();
return true;
}
catch (err) {
return false;
}
});
if (success) {
console.log("Authentication#register() :: successfully registered");
return res.status(200).json({message: "Successfully Registered"});
}
console.error("Authentication#register() :: error registering", error);
// probably not the message you want but left as-is...
return res.status(400).json({message: "Successfully Registered"});
});
This is untested since you haven't provided a complete, reproducible example.
page.exposeFunction is another possible tool for triggering Node code based on a condition in the browser, but that seems like overkill here.
Finally, I'm not sure what page is, but typically you need a different page for each request. See this answer for suggested Express + Puppeteer boilerplate.

Will the 'error' event ever be emitted on 'http.IncomingMessage' in a node.js http.request?

I can create 4 error scenarios when calling http.get(url, cb):
httpThrows()
Can be triggered with a wrong format of the url, or wrong callback, etc.
function httpThrows() {
try {
http.get("www.missing-protocol.com", res => {
console.log(res.statusCode);
});
} catch (error) {
console.log("http.get() throws an error.");
}
}
requestError()
It the main error handler and triggers on some network related issue, e.g. DNS lookup failed or server not responding, etc.
function requestError() {
var req = http.get("http://some-url-that-does-not-exist.com", res => {
console.log(res.statusCode);
});
req.on("error", err => {
console.log("req.on('error') called with error");
});
}
errorCode()
Server responded normally so no network errors (can handle server errors).
function errorCode() {
http.get("http://httpstat.us/501", res => {
console.log("Got error code:", res.statusCode);
});
}
responseError() (the problem)
An http.IncomingMessage is given in the callback as response or res. According to the documentation it is a Readable steam and that steam can emit an error event.
function responseError() {
http.get("http://some-ulr-with-error-halfway-through.com/", res => {
console.log(res.statusCode);
// This will never be emitted?
res.on("error", err => {
console.log("res.on('error') called with error", err);
});
});
}
So this last handler:
Is this event ever triggered when using http.request or http.get?
If so what can trigger the event?
For my understanding the only way to end up with an error in that case is if there would be an issue with Node or the Engine and in both cases you can't do much about it.
In this situations I prefer not to handle those cases because you have less code to review and maintain.

Trapping AssertionError in nested callback function

I am writing an updated testing library for Node.js and am trying to properly trap errors that occur in test callbacks
for some reason, the following code doesn't trap an AssertionError:
process.on('uncaughtException',function(err){
console.error(err); //an instance of AssertionError will show up here
});
[file1,file2,file2].forEach(function (file) {
self.it('[test] ' + path.basename(file), {
parallel:true
},function testCallback(done) {
var jsonDataForEnrichment = require(file);
request({
url: serverEndpoint,
json: true,
body: jsonDataForEnrichment,
method: 'POST'
}, function (error, response, body) {
if (error) {
done(error);
}
else {
assert(response.statusCode == 201, "Error: Response Code"); //this throws an error, which is OK of course
done();
}
});
});
});
I handle the callback (I named it "testCallback" above), with this code:
try {
if (!inDebugMode) {
var err = new Error('timed out - ' + test.cb);
var timer = setTimeout(function () {
test.timedOut = true;
cb(err);
}, 5000);
}
test.cb.apply({
data: test.data,
desc: test.desc,
testId: test.testId
}, [function (err) { //this anonymous function is passed as the done functon
cb(err);
}]);
}
catch (err) { //assertion error is not caught here
console.log(err.stack);
cb(err);
}
I assume the problem is that callbacks that result from async functions like those made in the request module, cannot be trapped by simple error handling.
What is the best way to trap that error?
Should I just flesh out the process.on('uncaughtException') handler? Or is there a better way?
The best way to handle this appears to be Node.js domains, a core module
https://nodejs.org/api/domain.html
it will likely be deprecated soon, but hopefully there will be a replacement that can have similar functionality, because the domain module is saving my ass right now, as I have no other way to trap errors, because the errors might be generated by my users' code, not my code.

Passing multiple error messages through callback?

I am using the got library to make some http requests. A typical got request looks like this:
got.post(url, options, function(err, body, res) {
...
}
The callback has errors as well as the body content and the full response. In some cases when connecting to certain 3rd party APIs, if I get an error response, I find both the err and body both contain important error information I would want to pass back up the chain of callbacks:
API.prototype.makeRequest = function(callback) {
got.post(url, {}, function(err, body, res) {
if (err) {
callback(err);
return false;
}
// Otherwise do stuff
});
}
// app.js
var myAPI = new API();
myAPI.makeRequest(function(err, data){
if (err) {
console.log(err);
return false;
}
// Do stuff...
});
So in this example, I'm obviously only returning the error for the response. An example of this error:
{ [HTTPError: Response code 400 (Bad Request)]
message: 'Response code 400 (Bad Request)',
code: undefined,
host: 'api.someservice.com',
hostname: 'api.someservice.com',
method: 'POST',
path: '/oauth2/token_access',
statusCode: 400,
statusMessage: 'Bad Request' }
But if I examine the body of the error request, I see even more important and relevant error information:
{ error_description: 'Grant type is not supported: some_type_of_grant', error: 'unsupported_grant_type' }
So I have useful information in both the err and body variables that I want to pass back up the callback chain since both are useful.
What is the best approach to this? Typical Node.js approach seems to be having a single err value be the first value in the callback. Should I combine them into a single object or combine them and formulate my own error? Any other good approaches?

Returning error object along with the hapijs boom object

I'm trying to return the error object inside the response of a boom internal error object but it keeps omitting the error object.
I tried to follow the answer here but it didn't help.
function (request, reply) {
options.healthCheck(function (err) {
if (!err) {
return reply('I\'m healthy!!!');
}
var boomErr = boom.internal('I don\'t feel so good', {
err: err
});
boomErr.output.payload.details = err;
return reply(boomErr);
});
}
Here is the response:
{
"statusCode":500,
"error":"Internal Server Error",
"message":"An internal server error occurred",
"details":{ }
}
After digging into boom docs, I found out that all 5xx errors hide the custom message and payload.
Switching to bad request error solved my issue.

Categories