How to Catch Error: connect ECONNREFUSED at TCPConnectWrap.afterConnect [as oncomplete] - javascript

I am using #nestjs/axios in my NestJS backend application to call an endpoint as bellow:
this.httpService.get('some url').pipe(
catchError(e => {
throw new InternalServerErrorException('error');
}),
map(res => {
console.log('succeeded');
})
);
The problem is that when the endpoint is available then the succeeded will be reached, but when the endpoint is not available the catchError is never reached and succeeded neither.

Related

Why nodejs is not allowing me to access other route when I access the root route?

I am using the HTTP module of nodejs to create three routes('/','/about' and the last one treats any other route that is not defined as error route). When I access the root route first and try to access other route nodejs throw an error but when I access the error route or the about the route and try accessing another route it works fine.
Below are the code I wrote and the error nodejs throw
Error
PS C:\Users\Maxwell\Desktop\node> node app.js
node:events:368
^
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at new NodeError (node:internal/errors:371:5)
at ServerResponse.end (node:_http_outgoing:846:15)
at Server.<anonymous> (C:\Users\Maxwell\Desktop\node\app.js:10:9)
at Server.emit (node:events:390:28)
at parserOnIncoming (node:_http_server:951:12)
at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17)
Emitted 'error' event on ServerResponse instance at:
at emitErrorNt (node:_http_outgoing:726:9)
at processTicksAndRejections (node:internal/process/task_queues:84:21) {
code: 'ERR_STREAM_WRITE_AFTER_END'
}
PS C:\Users\Maxwell\Desktop\node> node app.js
node:events:368
throw er; // Unhandled 'error' event
^
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at new NodeError (node:internal/errors:371:5)
at ServerResponse.end (node:_http_outgoing:846:15)
at Server.<anonymous> (C:\Users\Maxwell\Desktop\node\app.js:10:9)
at Server.emit (node:events:390:28)
at parserOnIncoming (node:_http_server:951:12)
at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17)
Emitted 'error' event on ServerResponse instance at:
at emitErrorNt (node:_http_outgoing:726:9)
at processTicksAndRejections (node:internal/process/task_queues:84:21) {
code: 'ERR_STREAM_WRITE_AFTER_END'
}
Code
const http = require('http');
const server = http.createServer((req,res)=>{
if(req.url==='/'){
res.end('Welcome Home Dev, You are loved');
}
if(req.url==='/about'){
res.end('This is the about page')
}
res.end(
`<h1>OOOp</h1>
<p>It seen like this page does not exit</p>
<a href='/'>back to homepage</a>
`
);
});
server.listen(5000);
Change to an if/else so you're only processing one branch of the if per request:
const server = http.createServer((req,res)=>{
if(req.url === '/'){
res.end('Welcome Home Dev, You are loved');
} else if (req.url === '/about') {
res.end('This is the about page')
} else {
res.end(
`<h1>OOOp</h1>
<p>It seen like this page does not exit</p>
<a href='/'>back to homepage</a>`);
}
});
Or, alternately, you could add a return after each res.send() to stop further execution in your request handler after you send a response. Remember, that just because you call res.send() your function still continues to execute so you need to manage control flow so the other code that sends a response doesn't execute once you've already sent a response.

How to test a promise that connects to RabbitMQ?

Hi I'm using Chai and trying to test a custom function that connects to RabbitMQ passing a wrong host:
connect(host) {
return new Promise((resolve, reject) => {
amqp.connect(host)
.then((conn) => {
resolve(conn);
})
.catch((err) => {
throw new Error(err);
});
});
}
If the connection fail I throw a Error, so I'm testing it like this:
it('shouldnt connect to RabbitMQ service successfully with the wrong host.', async () => {
const result = await rabbitmqmailer.connect('amqp://wronghost');
expect(result).to.equal(Error);
});
The connection fails and throws a error but my test is not testing that, simply I got the exception on my terminal:
RabbitMQMailer component.
RabbitMQMailer configuration information.
✓ should test rabbitmqmailer host configuration.
✓ should test rabbitmqmailer queue configuration.
✓ should get rabbitmqmailer empty emailContent value after make a new instance.
✓ should get rabbitmqmailer empty emailContentConsumed value after make a new instance.
✓ resolves
✓ should connect to RabbitMQ service successfully with the correct host. (60ms)
Unhandled rejection Error: Error: getaddrinfo EAI_AGAIN wronghost wronghost:5672
at _amqplib2.default.connect.then.catch.err (/home/ubuntu/Desktop/easy-tracking/backend/src/components/rabbitmqmailer/rabbitmqmailer.dal.js:1:11069)
at tryCatcher (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/promise.js:690:18)
at _drainQueueStep (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/async.js:138:12)
at _drainQueue (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/async.js:131:9)
at Async._drainQueues (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/async.js:147:5)
at Immediate.Async.drainQueues [as _onImmediate] (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/async.js:17:14)
at processImmediate (timers.js:632:19)
1) shouldnt connect to RabbitMQ service successfully with the wrong host.
I tried catching the exception on a trycatch block but it's the same issue.
EDIT: I got this error on terminal after changing my test to:
it('shouldnt connect to RabbitMQ service successfully with the wrong host.', async (done) => {
const result = await rabbitmqmailer.connect('amqp://wronghost');
expect(result).to.be.an.instanceof(Error);
done();
});
(node:18911) UnhandledPromiseRejectionWarning: Error: Error: getaddrinfo EAI_AGAIN wronghost wronghost:5672
at _amqplib2.default.connect.then.catch.err (/home/ubuntu/Desktop/easy-tracking/backend/src/components/rabbitmqmailer/rabbitmqmailer.dal.js:1:11475)
at tryCatcher (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/promise.js:690:18)
at _drainQueueStep (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/async.js:138:12)
at _drainQueue (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/async.js:131:9)
at Async._drainQueues (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/async.js:147:5)
at Immediate.Async.drainQueues (/home/ubuntu/Desktop/easy-tracking/backend/node_modules/amqplib/node_modules/bluebird/js/release/async.js:17:14)
at processImmediate (timers.js:632:19)
(node:18911) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:18911) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
1) shouldnt connect to RabbitMQ service successfully with the wrong host.
1) RabbitMQMailer component.
RabbitMQMailer configuration information.
shouldnt connect to RabbitMQ service successfully with the wrong host.:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/ubuntu/Desktop/easy-tracking/backend/src/components/rabbitmqmailer/rabbitmqmailer.test.js)
You are not properly failing. You forgot about the reject. Do this instead:
connect(host) {
return new Promise((resolve, reject) => {
amqp.connect(host)
.then((conn) => {
resolve(conn);
})
.catch((err) => {
reject(new Error(err)); // Pass the error to reject
});
});
}
In your test, use instanceof to match the Error that is returned:
it('shouldnt connect to RabbitMQ service successfully with the wrong host.', async () => {
const result = await rabbitmqmailer.connect('amqp://wronghost');
expect(result).to.be.an.instanceof(Error);
});
Also I don't know what you are using for testing, but if it is jest, then this link might help you properly test the promise.
EDIT: Actually nvm. I see you are using Chai
You need to reject the Promise.
connect(host) {
return new Promise((resolve, reject) => {
amqp.connect(host)
.then((conn) => resolve(conn))
.catch((err) => reject(new Error(err));
});
}
And the test
it('shouldnt connect to RabbitMQ service successfully with the wrong host.', () => {
return rabbitmqmailer.connect('amqp://wronghost')
.then(() => { assert.fail('was not supposed to succeed'); })
.catch((err) => { expect(err).to.be.an.instanceof(Error); })
})
You usually want your tests to be isolated. I would recommend mocking your amqp object and expect that the connect method is being called.
It's important that you try and understand the real connect method before designing the mock
You can use a mocking framework like https://sinonjs.org/
Finally I found the way to test it
it('shouldnt connect to RabbitMQ service successfully with the wrong host.', (done) => {
(async () => {
try {
await rabbitmqmailer.connect('amqp://wronghost');
} catch (error) {
chai.assert.typeOf(error, 'error');
} finally {
done();
}
})();
});
But there's some strange issue, if I change the type like a 'string' for example, it tells me:
(node:26053) UnhandledPromiseRejectionWarning: AssertionError: expected [Error: Error: getaddrinfo EAI_AGAIN wronghost wronghost:5672] to be a string
But ! the test passes successfully :
✓ shouldnt connect to RabbitMQ service successfully with the wrong host.
I don't know why it's happen but it works anyway, thanks for the help.

Catch error on IBM Watson IoT NodeJS client

I'm using the IBM Watson IoT NodeJS client to connect and use IBM Watson IoT.
This works when my object with credentials etc. is correct:
var client = new ibm_watson_iot.IotfGateway(MY-JSON-OBJECT-WITH-CREDENTIALS);
But if credentials is wrong, then I get:
events.js:160
throw er; // Unhandled 'error' event
^
Error: getaddrinfo ENOTFOUND 1234xyz.messaging.internetofthings.ibmcloud.com 1234xyz.messaging.internetofthings.ibmcloud.com:8883
at errnoException (dns.js:28:10)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26)
error: Forever detected script exited with code: 1
How do I correctly catch this error in a nice way?
You can always use try/catch block to handler error like that
try{
var client = new ibm_watson_iot.IotfGateway(MY-JSON-OBJECT-WITH-CREDENTIALS);
}
catch(error) {
console.log("Error in connection.. Probably configuration object")
}

node-transmission package not working

I tried installing this package : https://github.com/FLYBYME/node-transmission in my local nodejs installation but I am getting following error while running example.js from the above github repository.
Error: connect ECONNREFUSED 127.0.0.1:9091
at Object.exports._errnoException (util.js:1022:11)
at exports._exceptionWithHostPort (util.js:1045:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1090:14)
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 9091
After a bit research I tried to run a server at port 9091 using this code(in a separate server.js file)
const http = require('http')
const port = 9091
const requestHandler = (request, response) => {
console.log(request.url)
response.end('Hello Node.js Server!')
}
const server = http.createServer(requestHandler)
server.listen(port, (err) => {
if (err) {
return console.log('something bad happened', err)
}
console.log(`server is listening on ${port}`)
})
After running a server on port 9091, I started getting this error with example.js :
SyntaxError: Unexpected token H in JSON at position 0
at JSON.parse (<anonymous>)
at IncomingMessage.onEnd (F:NodeJS\node-transmission-master\lib\transmission.js:453:33)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
What must be causing this? I have no idea which step I have done wrong. That's why I described the whole process I followed.
I am very new to nodejs. Any help will be deeply appreciated.
The library is expecting a JSON formatted response and you are sending a simple text response. If you look through their source code you can see that their callServer function expects a stringified JSON but I can't see that in their docs.
You can change your code like so:
const http = require('http')
const port = 9091
const requestHandler = (request, response) => {
console.log(request.url)
// Format your response as a stringified JSON
response.end(JSON.stringify({message: 'Hello Node.js Server!'}));
}
const server = http.createServer(requestHandler)
server.listen(port, (err) => {
if (err) {
return console.log('something bad happened', err)
}
console.log(`server is listening on ${port}`)
})
In order to run the example from the node-transmission package, you need first to install and start the transmission-daemon.
The following steps are for Ubuntu:
Login as root or change to root with su - (be always careful what you do/install as root)
Install the transmission-daemon linux package: apt-get install transmission-daemon
Edit the daemon configuration for either disabling authentication or setting up your username/password (there is no default password). You can disable authentication by editing the relative flag in the configuration file:
pico /etc/transmission-daemon/settings.json
Set the auth flag to false: rpc-authentication-required:false
Press Ctrl-X then Y and then Enter to save the change
Start the daemon: start transmission-daemon
You should be able now to execute successfully the example.js and download its torrent link.

How to handle an ETIMEDOUT in node.js using http2?

My knowledge of node.js isn't very good and I might be missing something obvious.
I need to "crawl" a list of urls (combination of http-https, hosts and ports) for an experiment. One of those urls is not responding (it does locally, so I guess one of the middleboxes is blocking) it, which it's fine but I breaks my app as I'm not able to catch the error:
var http2 = require('http2');
var req = http2.raw.get('http://xxx.yyy.zzz.a:23/', function(response) {
var content = '';
response.on('data', function(chunk) {
content += chunk;
})
response.on('end', function() {
console.log(content);
console.log('end');
});
});
req.on('error', function(error) {
console.error(error);
});
It throws the following Error (catched it with process.on('uncaughtException', ...)):
{ [Error: connect ETIMEDOUT xxx.yyy.zzz.a:23]
code: 'ETIMEDOUT',
errno: 'ETIMEDOUT',
syscall: 'connect',
address: 'xxx.yyy.zzz.a',
port: 23 }
Error: connect ETIMEDOUT xxx.yyy.zzz.a:23
at Object.exports._errnoException (util.js:814:11)
at exports._exceptionWithHostPort (util.js:837:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1044:14)
Try-catch does not work, because the function is async.
request.on('error') does not seem to catch this error. setTimeout is not implemented in this library.
I think I need to add an event into the TCP connection, but I don't know how.
I'm using node.js 0.12.7 and http2 3.2.0
Any ideas? Really appreciated

Categories