Node: Cannot set headers after they are sent to the client - node.js

I did some research on the following error:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I understood the idea and what's causing it but I am not sure how to fix it for my controller code:
exports.isServerOnline = (req, res, next) => {
const sock = new net.Socket();
sock.setTimeout(2500);
sock.on('connect', function () {
sock.destroy();
return res.json({
"server": "online"
});
}).on('error', function (e) {
return res.json({
"server": "offline"
});
}).on('timeout', function (e) {
return res.json({
"server": "offline"
});
}).connect(LS_PORT, LS_HOST);
}
I'm using socket to check if a remote host is up or down. Here is my client code (Vue.js):
created() {
this.getServerStatus();
},
methods: {
getServerStatus() {
axios
.get(`${process.env.VUE_APP_BACKEND_URL}/server/status`)
.then(response => {
if (response.data.server === "online") {
// no interesting code here
} else {
// no interesting code here
}
/* eslint-disable no-console */
})
.catch(error => {
console.log(error);
});
}
}
Complete error stack trace:
2020-07-02T07:40:47.743193+00:00 app[web.1]: _http_outgoing.js:518
2020-07-02T07:40:47.743201+00:00 app[web.1]: throw new ERR_HTTP_HEADERS_SENT('set');
2020-07-02T07:40:47.743202+00:00 app[web.1]: ^
2020-07-02T07:40:47.743202+00:00 app[web.1]:
2020-07-02T07:40:47.743204+00:00 app[web.1]: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
2020-07-02T07:40:47.743205+00:00 app[web.1]: at ServerResponse.setHeader (_http_outgoing.js:518:11)
2020-07-02T07:40:47.743206+00:00 app[web.1]: at ServerResponse.header (/app/node_modules/express/lib/response.js:771:10)
2020-07-02T07:40:47.743206+00:00 app[web.1]: at ServerResponse.json (/app/node_modules/express/lib/response.js:264:10)
2020-07-02T07:40:47.743206+00:00 app[web.1]: at Socket.<anonymous> (/app/src/controllers/status.js:15:20)
2020-07-02T07:40:47.743207+00:00 app[web.1]: at Socket.emit (events.js:315:20)
2020-07-02T07:40:47.743207+00:00 app[web.1]: at emitErrorNT (internal/streams/destroy.js:92:8)
2020-07-02T07:40:47.743208+00:00 app[web.1]: at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
2020-07-02T07:40:47.743208+00:00 app[web.1]: at processTicksAndRejections (internal/process/task_queues.js:84:21) {
2020-07-02T07:40:47.743209+00:00 app[web.1]: code: 'ERR_HTTP_HEADERS_SENT'
2020-07-02T07:40:47.743209+00:00 app[web.1]: }
I would highly appreciate if someone could point me on the right track.

I don't think that approach is correct mate. You are trying to create a socket inside http endpoint, that will not work. Here's gist I found that demonstrates using NodeJS Socket.
https://gist.github.com/tedmiston/5935757
I'll recommend using into something like Socket.io. They have good amount of documentation to get off the ground.

Related

sp-request : trying get file details from sharepoint returns ECONNREFUSED

I have the following code that successfully uploads test.sspkg to my sharepoint app catalog. Now I'm trying to use sp-request to prove that it's actually there.
But I'm getting an ECONNREFUSED error.
Error message
This shows the error:
[14:24:15] INFO: Checking if file (test.sppkg) is checked out
[14:24:15] INFO: File checkout type: 0
[14:24:17] Published file 1482ms
[14:24:17] And we're done...
trying to retrieve: https://mytenant.sharepoint.com/sites/JJTest/_api/web/GetFileByServerRelativeUrl(#FileUrl)/$value?#FileUrl='%2Fsites%2FJJTest%2FAppCatalog%2Ftest.sppkg'
errored out
{ GotError: connect ECONNREFUSED 127.0.0.1:443
at onError (/src/myplugins/node_modules/got/dist/source/request-as-event-emitter.js:140:29)
at ClientRequest.request.on.error (/src/myplugins/node_modules/got/dist/source/request-as-event-emitter.js:157:17)
at ClientRequest.emit (events.js:203:15)
at ClientRequest.EventEmitter.emit (domain.js:448:20)
at ClientRequest.origin.emit.args (/src/myplugins/node_modules/#szmarczak/http-timer/dist/source/index.js:43:20)
at TLSSocket.socketErrorListener (_http_client.js:401:9)
at TLSSocket.emit (events.js:198:13)
at TLSSocket.EventEmitter.emit (domain.js:448:20)
at emitErrorNT (internal/streams/destroy.js:91:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:59:3)
at process._tickCallback (internal/process/next_tick.js:63:19)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1107:14) name: 'RequestError', code: 'ECONNREFUSED' }
Package
This is the node package I'm using to call the SP API:
"dependencies": {
"sp-request": "^3.0.0"
}
Code:
const sprequest = require('sp-request');
await new Promise((resolve, reject) => {
gulp
.src(folderLocation)
.pipe(
spsync({
username: uname,
password: pwd,
site: siteCatalogUrl + "/",
libraryPath: catalogName,
publish: true,
verbose: true
}))
.on("finish", () => {
var spr = sprequest.create({ username: uname, password: pwd });
//https://mytenant.sharepoint.com/sites/JJTest/_api/web/getFileByServerRelativeUrl('/sites/JJTest/AppCatalog/test.sppkg')
var filepath = `${siteCatalogUrl}/_api/web/GetFileByServerRelativeUrl(#FileUrl)/$value?#FileUrl='${encodeURIComponent("/sites/JJTest/AppCatalog/test.sppkg")}'`;
console.log('trying to retrieve: ' + filepath);
var retrieveFileUrl = filepath;
spr.get(filepath, {
encoding:null
})
.then(data => {
expect(fileContent.equals(data.body)).is.true;
resolve();
})
.catch(data => {
console.log('errored out')
console.log(data)
reject();
});
resolve();
});
});
What I've tried:
I have tried just copying parts of the output from my console directly into the browser. Specifically, this is the output i get from my debug print statement:
trying to retrieve: https://mytenant.sharepoint.com/sites/JJTest/_api/web/GetFileByServerRelativeUrl/(#FileUrl)/$value?#FileUrl='%2Fsites%2FJJTest%2FAppCatalog%2Ftest.sppkg'
errored out
Pasting this:
https://mytenant.sharepoint.com/sites/JJTest/_api/web/GetFileByServerRelativeUrl('/sites/JJTest/AppCatalog/test.sppkg')
into a browser as the URL works. It returns the details of the file to me.
Can you tell me where I've gone wrong? maybe the syntax of substituting the #FileUrl?
I am using gulp version 3.9.1. And I just did a install latest of chai and sp-request.
But tried changing the specific versions to:
"sp-request": "^2.1.3"
"gulp": "^3.9.1",
"gulp-spsync-creds": "2.3.8",
"chai": "3.5.0"
And now, it's happy! it worked!

imageMagick fails at socket instance

I'm using the imageMagick subclass of graphicsmagick to alter ~7k png images. The function below gets about 2/3 of the way through and fails (see log).
Seems to be an issue where a socket is failing. How do I debug this?
A thought I have is to use the -limit method, but no dice...
Thanks in advance :)
Code:
// changing an image's resolution is the same thing as changing its DPI
export default async function changeScreenshotResolution(dimension) {
new Promise(() => {
try {
const screenshots = fs.readdirSync(path.join(__dirname, `../output/screenshots/${dimension}`), function(error) {if (error) console.log(error)});
screenshots.map(screenshot => {
try {
let readStream = fs.createReadStream(path.join(__dirname, `../output/screenshots/${dimension}/${screenshot}`));
let writeStream = fs.createWriteStream(path.join(__dirname, `../output/screenshots/${dimension}1/${screenshot}`));
im(readStream, screenshot)
.limit('memory', '32MB') // i tried variations of this but it made no difference
.units('PixelsPerInch')
.density(300,300)
.stream()
.pipe(writeStream)
console.log(screenshot);
} catch (error) {
console.log(`Error changing screenshot resolution: ${error}`);
}
})
} catch (error) {
console.log(`changeScreenshotResolution error: ${error}`);
}
})
};
Error: spawn convert EAGAIN
at Process.ChildProcess._handle.onexit (internal/child_process.js:268:19)
at onErrorNT (internal/child_process.js:468:16)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
errno: -35,
code: 'EAGAIN',
syscall: 'spawn convert',
path: 'convert',
spawnargs: [
'-density',
'300x300',
'/Users/daddy/Dev/scout/project-sunroof-scraping/output/screenshots/rect/6550 ARABIAN CIR.png',
'-units',
'PixelsPerInch',
'/Users/daddy/Dev/scout/project-sunroof-scraping/output/screenshots/rect1/6550 ARABIAN CIR.png'
]
}
events.js:292
throw er; // Unhandled 'error' event
^
Error: read ENOTCONN
at tryReadStart (net.js:571:20)
at Socket._read (net.js:582:5)
at Socket.Readable.read (_stream_readable.js:474:10)
at Socket.read (net.js:622:39)
at new Socket (net.js:374:12)
at Object.Socket (net.js:265:41)
at createSocket (internal/child_process.js:313:14)
at ChildProcess.spawn (internal/child_process.js:436:23)
at Object.spawn (child_process.js:548:9)
at spawn (/Users/daddy/Dev/scout/project-sunroof-scraping/node_modules/cross-spawn/index.js:17:18)
at gm._spawn (/Users/daddy/Dev/scout/project-sunroof-scraping/node_modules/gm/lib/command.js:224:14)
at /Users/daddy/Dev/scout/project-sunroof-scraping/node_modules/gm/lib/command.js:101:12
at series (/Users/daddy/Dev/scout/project-sunroof-scraping/node_modules/array-series/index.js:11:36)
at gm._preprocess (/Users/daddy/Dev/scout/project-sunroof-scraping/node_modules/gm/lib/command.js:177:5)
at gm.write (/Users/daddy/Dev/scout/project-sunroof-scraping/node_modules/gm/lib/command.js:99:10)
at /Users/daddy/Dev/scout/project-sunroof-scraping/modules/changeScreenshotDPI.js:18:26
Emitted 'error' event on Socket instance at:
at emitErrorNT (internal/streams/destroy.js:100:8)
at emitErrorCloseNT (internal/streams/destroy.js:68:3)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
errno: -57,
code: 'ENOTCONN',
syscall: 'read'
}

If I disable NODE_TLS_REJECT_UNAUTHORIZED, my request is still denied

I am disabling Node from rejecting self signed certificates and making a request.
const { USER, PW } = process.env;
const b64 = new Buffer(`${VP_API_USER}:${VP_API_PW}`).toString("base64");
const Authorization = `Basic ${b64}`;
const doFind = async url => {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
const results = await fetch(url, { headers: { Authorization } })
.then(r => (r.ok ? r.json() : Promise.reject(r)))
.catch(err => {
return Promise.reject(err);
});
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 1;
return results;
};
I am still being rejected.
{ FetchError: request to https://<url>:55544/contracts failed, reason: connect ECONNREFUSED <url>:55544
at ClientRequest.<anonymous> (/Users/mjhamm75/Developer/sedd-monorepo/node_modules/node-fetch/index.js:133:11)
at emitOne (events.js:116:13)
at ClientRequest.emit (events.js:211:7)
at TLSSocket.socketErrorListener (_http_client.js:387:9)
at emitOne (events.js:116:13)
at TLSSocket.emit (events.js:211:7)
at emitErrorNT (internal/streams/destroy.js:64:8)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)
name: 'FetchError',
message: 'request to https://<url>:55544/contracts failed, reason: connect ECONNREFUSED <url>:55544',
type: 'system',
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED' }
What am I doing wrong?
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 1;
line should go inside the callback (your then or catch before the return. because a promise gets resolved in the callback, but your line
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 1;
is written outside of it, even though it appears after the statement, it runs immediately without waiting for the callback. so, your tls is effectively never disabled.
I hope this helps:)
Previous answer looks incorrect - await postpones execution of next line until promise will be resolved.
According to the documentation the NODE_TLS_REJECT_UNAUTHORIZED value should be string '0' to disable TLS validation.
This is how I would approach it, if I had to reset the env var afterwards.
Using .finally() the statement will execute regardless of the outcome of the fetch.
const doFind = async url => {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
const results = await fetch(url, { headers: { Authorization } })
.then(r => (r.ok ? r.json() : Promise.reject(r)))
.catch(err => {
return Promise.reject(err);
})
.finally(() => {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 1;
});
return results;
};

throw new RangeError node js

I'm trying to work with IBM Watson Conversation service with Node.js.
I use 'express' to post a message:
app.post( '/api/message', function(req, res) {
}
and to print the message got from the service:
conversation.message( payload, function(err, data) {
if ( err ) {
return res.status( err.code || 500 ).json( err );
}
return res.json( updateMessage( payload, data ) );
} );
I just ran the application on port 3000. While the page is not loaded and I got this error:
_http_server.js:192
throw new RangeError(`Invalid status code: ${statusCode}`);
^
RangeError: Invalid status code: 0
at ServerResponse.writeHead (_http_server.js:192:11)
at ServerResponse._implicitHeader (_http_server.js:157:8)
at ServerResponse.OutgoingMessage.end (_http_outgoing.js:573:10)
at ServerResponse.send (C:\IBM\1.Mission\2016\conversation-simple-master(1)\
conversation-simple-master\node_modules\express\lib\response.js:204:10)
at ServerResponse.json (C:\IBM\1.Mission\2016\conversation-simple-master(1)\
conversation-simple-master\node_modules\express\lib\response.js:249:15)
at C:\IBM\1.Mission\2016\conversation-simple-master(1)\conversation-simple-m
aster\app.js:86:44
at Request._callback (C:\IBM\1.Mission\2016\conversation-simple-master(1)\co
nversation-simple-master\node_modules\watson-developer-cloud\lib\requestwrapper.
js:47:7)
at self.callback (C:\IBM\1.Mission\2016\conversation-simple-master(1)\conver
sation-simple-master\node_modules\watson-developer-cloud\node_modules\request\re
quest.js:200:22)
at emitOne (events.js:77:13)
at Request.emit (events.js:169:7)
I don't think the problem is from npm, back my package... While it seems a generic problem...Thanks for you help.
Request to IBM Watson Conversation service probably ended with error with code "0" and it isn't a valid HTTP status code. This should work:
conversation.message(payload, function(err, data) {
if (err) {
return res.status(500).json(err);
}
return res.json(updateMessage(payload, data));
});

Node.js and Sendgrid mailer error on res.end

I'm a bit new to node. I'm using express and the sendgrid api to send an email (collected REST-fully). After sendgrid succeeds or fails, I want to respond with a json object. Here's the sample case:
var SendGrid = require('sendgrid-nodejs').SendGrid;
var sendgrid = new SendGrid(user, key);
app.get('/LGP/:email', function (req, res){
sendgrid.send({
to: req.params.email,
from: 'me#example.com',
subject: 'Hello World',
text: 'This email sent through SendGrid'
}, function(success, message) {
if (!success) {
console.log(message);
} else {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.write(JSON.stringify({ result: 'success' }));
res.end(); //error occurs: "Can't use mutable header APIs after sent."
}
}
);
});
On my local server (using foreman), everything works fine. But when I push it to heroku, it gives me this stack trace:
2013-02-27T22:12:46+00:00 app[web.1]: http.js:543
2013-02-27T22:12:46+00:00 app[web.1]: throw new Error("Can't use mutable header APIs after sent.");
2013-02-27T22:12:46+00:00 app[web.1]: ^
2013-02-27T22:12:46+00:00 app[web.1]: Error: Can't use mutable header APIs after sent.
2013-02-27T22:12:46+00:00 app[web.1]: at ServerResponse.getHeader (http.js:543:11)
2013-02-27T22:12:46+00:00 app[web.1]: at /app/node_modules/express/node_modules/connect/lib/middleware/logger.js:229:26
2013-02-27T22:12:46+00:00 app[web.1]: at ServerResponse.<anonymous> (/app/node_modules/express/node_modules/connect/lib/middleware/logger.js:149:20)
2013-02-27T22:12:46+00:00 app[web.1]: at /app/app.js:60:13
2013-02-27T22:12:46+00:00 app[web.1]: at IncomingMessage.<anonymous> (/app/node_modules/sendgrid/lib/sendgrid.js:74:9)
2013-02-27T22:12:46+00:00 app[web.1]: at IncomingMessage.emit (events.js:81:20)
2013-02-27T22:12:46+00:00 app[web.1]: at HTTPParser.onMessageComplete (http.js:133:23)
2013-02-27T22:12:46+00:00 app[web.1]: at CleartextStream.ondata (http.js:1213:22)
2013-02-27T22:12:46+00:00 app[web.1]: at CleartextStream._push (tls.js:291:27)
2013-02-27T22:12:46+00:00 app[web.1]: at SecurePair._cycle (tls.js:565:20)
2013-02-27T22:12:48+00:00 heroku[web.1]: Process exited with status 1
2013-02-27T22:12:48+00:00 heroku[web.1]: State changed from up to crashed
/app/app.js:60:13 refers to the line with "res.end()". What am I doing wrong?
To maximize your chances of your app behaving the same locally and on heroku, you should make sure you specify specific versions for all modules and avoid using "*" for the main dependencies.
Should also should specify the node version in package.json:
"engines": {
"node": "0.8.20"
}
(use whatever version is appropriate).

Resources