Node: Can't bind to IPv6 localAddress while using https.request() - node.js

I can bind to localAddress just fine when using HTTP, but as soon as I switch to HTTPS I get an error: bind EINVAL. Please consider this code:
var http = require('http');
var https = require('https');
var options = { host:'icanhazip.com',path:'/',localAddress:'2604:a880:1:20::27:a00f',family:6 };
callback = function(response) {
var data = '';
response.on('data',function(chunk) { data+= chunk; });
response.on('error',function(error) { console.log("error: "+error.message); });
response.on('end',function() {
console.log(data);
});
}
http.request(options,callback).end(); // Works. IP:2604:a880:1:20::27:a00f
https.request(options,callback).end(); // Fails. IP:2604:a880:1:20::27:a00f
https.request({host:'icanhazip.com',path:'/',family:6},callback).end(); // Works. IP:2604:a880:1:20::27:a00f
Here's the error while running node v5.0.0:
Error: bind EINVAL 2604:a880:1:20::27:a00f
at Object.exports._errnoException (util.js:860:11)
at exports._exceptionWithHostPort (util.js:883:20)
at connect (net.js:809:16)
at net.js:984:7
at GetAddrInfoReqWrap.asyncCallback [as callback] (dns.js:63:16)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:82:10)
The only difference between the working and the failing code is setting localAddress and ironically, the last example binds to the correct IP address, but won't let you do it using localAddress.
The problem here is I have to make a request from a completely separate IPv6 address under my use case, and it works fine with HTTP but I need this to work for HTTPS requests. Currently I can only make this work while using cURL. Could you please provide some insight as to why this is happening or how I could make this work without additional libraries?

I had same issue as you. Figured it out. Update your node to the latest stable. They fixed it. Check it with node --version I'm on 6.6.0 and it works great.
The version I got from doing an apt-get was way too old.

Related

Mongoose can't connect: Error: querySrv ENOTIMP mongodb.tcp.cluster1-owfxv.mongodb.net

Mongoose can't connect to mogodb Atlas. It every times give me this error:
Error: querySrv ENOTIMP _mongodb._tcp.cluster1-owfxv.mongodb.net
I am running inside kubernetes cluster inside minikube locally.
If I run project directly then it works perfectly but with minikube it alwasy give me error.
Following is my code:
const url = "mongodb+srv://name:password#cluster1-owfxv.mongodb.net/test?retryWrites=true";
const mongoDbOptions = {
useNewUrlParser: true,
reconnectTries: 10,
autoReconnect: true
};
mongoose.connect(url, mongoDbOptions).then((r) => { }).catch((e) => {
console.log(e);
});
Error message is not so clear to me. Its strange that it works directly but with kubernetes cluster it does not work.
I will really appreciate for any contribution.
Try using connection string compatible with mongo driver 2.2.12 or later i.e. one with mongodb://username:password#host1:port,host2:port,host3:port/databaseName
It's not clear why connection to mongodb is not working with new url.
Using older url, as stated by #cEeNikC, even works when mongoose is giving the following error-
Error: querySrv ETIMEOUT _mongodb._tcp.cluster0.aq9un.mongodb.net
at QueryReqWrap.onresolve [as oncomplete] (dns.js:203:19) {
errno: 'ETIMEOUT',
code: 'ETIMEOUT',
syscall: 'querySrv',
hostname: '_mongodb._tcp.cluster0.aq9un.mongodb.net'
}
go to your cluster setting and enable access from all IP addresses (if you doing this for a learning purpose because it's not safe) .
I add this "&w=majority" and worked:
Before: mongodb+srv://:#sdq25.lepde.mongodb.net/myFirstDatabase?retryWrites=true
After: mongodb+srv://:#sdq25.lepde.mongodb.net/myFirstDatabase?retryWrites=true&w=majority

intern 2 configuration for BrowserStack behind a proxy

I'm unsure what the configuration should be running intern 2 tests against BrowserStack when running behind a proxy/firewall and currently seeing errors/timeouts.
My Current configuration is:
proxyPort : 9000,
proxyUrl : 'http://localhost:9000',
tunnel : 'BrowserStackLocal',
tunnelOptions : {
username : 'myusername',
accessKey : 'myaccesskey',
hostname : '<myproxyip>',
proxy : 'http://<myproxyip>:<myproxyport>'
}
I don't think I need hostname however if I remove that I immediately see the error getaddrinfo ENOTFOUND.
If use the above configuration it seems to get further, waits for a while then see:
Listening on 0.0.0.0:9000
Starting tunnel...
BrowserStackLocal v3.3
Connecting to BrowserStack using WebSocket protocol...
Connected.
Ready
Error: [POST http://(redacted)#<myproxyip>:4444/wd/hub/session] connect ETIMEDOUT
Error: connect ETIMEDOUT
at errnoException <net.js:904:11>
at Object.afterConnect [as oncomplete] <net.js:895:19>
FATAL ERROR
Error: [POST http://(redacted)#<myproxyip>:4444/wd/hub/session] connect ETIMEDOUT
Error: connect ETIMEDOUT
at errnoException <net.js:904:11>
The [POST http://(redacted)#<myproxyip>:4444/wd/hub/session] url doesn't seem right. Obviously I have this misconfigured & would appreciate any advice. I do struggle to understand intern's documentation when running behind a proxy.
It looks like you are behind some kind of proxy.
When you are behind proxy server, in order to use Intern with BrowserStack, you need to do two things:
Get Local Testing connection to work with your proxy, which you are doing, and you can see success message.
You have to make sure the node process that runs the Intern test works with your proxy. To enable proxy in a node application, the easiest option is to use global-tunnel npm package. There is a step-by-step guide available here.
Would love to answer any queries you might have! Do drop in a mail at support#browserstack.com
Umang,
BrowserStack Support.
I'm not sure but I think there is a bug in browserStack.js. Some proxy support is missing there I think. When I use configuration browserstack_conf.js as shown below tests run okay but there is an error message when Browserstack tries to publish the test results back to www.browserstack.com
[09:43:06] E/launcher - connect ETIMEDOUT 54.152.200.70:443
[09:43:06] E/launcher - Error: connect ETIMEDOUT 54.152.200.70:443
at Object.exports._errnoException (util.js:1018:11)
at exports._exceptionWithHostPort (util.js:1041:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1090:14)
[09:43:06] E/launcher - Process exited with error code 199
I can fix this error with following steps:
npm install -g http-proxy-agent
Edit browserStack.js (located for example in C:\Users\myuser\AppData\Romaing\npm\node_modules\protractor\built\driverProviders\ add a require for this and initialize a agent and add to request.
For example add require top of browserStack.js
var HttpProxyAgent = require('http-proxy-agent');
And change the section with options to
let options = {
hostname: 'www.browserstack.com',
port: 443,
path: '/automate/sessions/' + session.getId() + '.json',
method: 'GET',
headers: headers//,
agent: new HttpProxyAgent('http://myproxy:3128')
};
I start Protractor with configuration below
// browserstack.conf.js
var browserstack = require('browserstack-local');
exports.config = {
specs: ['spec.js'],
webDriverProxy: 'http://myproxy:3128',
browserstackUser: 'myuser',
browserstackKey: '*****',
capabilities: {
project: 'BrowserStack (beyond Proxy)',
browserName: 'Chrome',
browser_version: '50.0',
os: 'OS X',
os_version: 'Yosemite',
'browserstack.local': true,
'browserstack.debug': true
},
// Code to start browserstack local before start of test
beforeLaunch: function(){
console.log("Connecting local");
return new Promise(function(resolve, reject){
exports.bs_local = new browserstack.Local();
exports.bs_local.start({'key': '*****',
'proxyHost': 'myproxy', 'proxyPort': '3128',
'binarypath': 'C:\\Users\\myuser\\Downloads\\BrowserStackLocal-win32\\BrowserStackLocal.exe'},
function(error) {
if (error) return reject(error);
console.log('Connected. Now testing...');
resolve();
});
});
},
// Code to stop browserstack local after end of test
afterLaunch: function(){
return new Promise(function(resolve, reject){
exports.bs_local.stop(resolve);
});
}
};

NodeJS Proxy Router Table

I'm trying to make a NodeJS http-proxy with a Router Table.
I saw some examples using http-proxy and try like this :
var httpProxy = require('http-proxy');
var proxyTable = {};
proxyTable['testproxy.com/toto'] = 'google.com:80';
proxyTable['testproxy.com/tata'] = 'gmail.com:80';
var httpOptions = {
router: proxyTable
};
console.log('Proxy Server Listening on port 80');
console.log('Requests to textproxy.com/toto (on port 80) are redirected to google.com:80');
console.log('Requests to textproxy.com/tata (on port 80) are redirected to gmail.com:80');
httpProxy.createServer(httpOptions).listen(80);
FYI : testproxy.com refer to 127.0.0.1.
It seems to work (it only intercepts request to testproxy.com/toto and tata) but when I try :
curl http://testproxy.com/toto
I have a NodeJS error :
var proxyReq = (options.target.protocol === 'https:' ? https : http).reque
^
TypeError: Cannot read property 'protocol' of undefined
at Array.stream [as 3] (D:\workspace\Proxy W_S\node_modules\http-proxy\l
ib\http-proxy\passes\web-incoming.js:103:35)
at ProxyServer.<anonymous> (D:\workspace\Proxy W_S\node_modules\http-pro
xy\lib\http-proxy\index.js:83:21)
at Server.closure (D:\workspace\Proxy W_S\node_modules\http-proxy\lib\ht
tp-proxy\index.js:125:43)
at Server.EventEmitter.emit (events.js:98:17)
at HTTPParser.parser.onIncoming (http.js:2108:12)
at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:121:23
)
at Socket.socket.ondata (http.js:1966:22)
at TCP.onread (net.js:525:27)
Is router table already supported by http-proxy module ?
I have to do a dynamic proxy, any idea ?
I'm new at NodeJS, and I'm stuck.
Thanks a lot for your answers.
Pierre-Luc
It seems that proxy table routing was removed from node-http-proxy when they released version 1.0.0.
However, they provided a new way of doing it using the new API:
https://blog.nodejitsu.com/node-http-proxy-1dot0/

TLS Error: socket hang up in nodejs

I'am trying to connect on a server using tls in nodejs. Here is my code :
var options = {
rejectUnauthorized: false //self signed certificate
};
co = require("tls").connect(5200, "my_host", options, function(){
co.on("data", function(data) {
//do domething
})
}
This is simplified code. If I catch the error event, I have a ECONNRESET error, if I don't, I've got this trace :
Error: socket hang up
at SecurePair.error (tls.js:1001:23)
at EncryptedStream.CryptoStream._done (tls.js:697:22)
at EncryptedStream.read [as _read] (tls.js:493:12)
at EncryptedStream.Readable.read (_stream_readable.js:320:10)
at CleartextStream.onCryptoStreamFinish (tls.js:301:47)
at CleartextStream.g (events.js:175:14)
at CleartextStream.EventEmitter.emit (events.js:92:17)
at finishMaybe (_stream_writable.js:354:12)
at endWritable (_stream_writable.js:361:3)
at CleartextStream.Writable.end (_stream_writable.js:339:5)
If I connect directly to my server using openssl s_client -connect my_host:5200 it works great. Strange thing, with node version 0.10.*, it works on ubuntu 10.04, but not on my mac neither on ubuntu 12.04. My server is also a nodejs program running ubuntu 10.04. Not sure if all of this is related but any help would be great !
Cheers
Depending on what your client/server are doing, there may be a timing issue here. You want to set your event-handlers outside the callback to ensure they are setup before data is flowing. Try this:
var options = {
rejectUnauthorized: false //self signed certificate
};
co = require("tls").connect(5200, "my_host", options, function(){
//do something
});
co.on("data", function(data) {
//do something
});

Node.js getaddrinfo ENOTFOUND

When using Node.js to try and get the html content of the following web page:
eternagame.wikia.com/wiki/EteRNA_Dictionary
I get the following error:
events.js:72
throw er; // Unhandled 'error' event
^
Error: getaddrinfo ENOTFOUND
at errnoException (dns.js:37:11)
at Object.onanswer [as oncomplete] (dns.js:124:16)
I did already look up this error on stackoverflow, and realized that this is because node.js cannot find the server from DNS (I think). However, I am not sure why this would be, as my code works perfectly on www.google.com.
Here is my code (practically copied and pasted from a very similar question, except with the host changed):
var http = require("http");
var options = {
host: 'eternagame.wikia.com/wiki/EteRNA_Dictionary'
};
http.get(options, function (http_res) {
// initialize the container for our data
var data = "";
// this event fires many times, each time collecting another piece of the response
http_res.on("data", function (chunk) {
// append this chunk to our growing `data` var
data += chunk;
});
// this event fires *one* time, after all the `data` events/chunks have been gathered
http_res.on("end", function () {
// you can use res.send instead of console.log to output via express
console.log(data);
});
});
Here is the source where I copied and pasted from : How to make web service calls in Expressjs?
I am not using any modules with node.js.
Thanks for reading.
In Node.js HTTP module's documentation: http://nodejs.org/api/http.html#http_http_request_options_callback
You can either call http.get('http://eternagame.wikia.com/wiki/EteRNA_Dictionary', callback), the URL is then parsed with url.parse(); or call http.get(options, callback), where options is
{
host: 'eternagame.wikia.com',
port: 8080,
path: '/wiki/EteRNA_Dictionary'
}
Update
As stated in the comment by #EnchanterIO, the port field is also a separate option; and the protocol http:// shouldn't be included in the host field. Other answers also recommends the use of https module if SSL is required.
Another common source of error for
Error: getaddrinfo ENOTFOUND
at errnoException (dns.js:37:11)
at Object.onanswer [as oncomplete] (dns.js:124:16)
is writing the protocol (https, https, ...) when setting the host property in options
// DON'T WRITE THE `http://`
var options = {
host: 'http://yoururl.com',
path: '/path/to/resource'
};
in the options for the HTTP request, switch it to
var options = { host: 'eternagame.wikia.com',
path: '/wiki/EteRNA_Dictionary' };
I think that'll fix your problem.
My problem was that my OS X (Mavericks) DNS service needed to be restarted. On Catalina and Big Sur DNS cache can be cleared with:
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
Older macOS versions see here.
If you need to use https, then use the https library
https = require('https');
// options
var options = {
host: 'eternagame.wikia.com',
path: '/wiki/EteRNA_Dictionary'
}
// get
https.get(options, callback);
var http=require('http');
http.get('http://eternagame.wikia.com/wiki/EteRNA_Dictionary', function(res){
var str = '';
console.log('Response is '+res.statusCode);
res.on('data', function (chunk) {
str += chunk;
});
res.on('end', function () {
console.log(str);
});
});
I think http makes request on port 80, even though I mentioned the complete host url in options object. When I run the server application which has the API, on port 80, which I was running previously on port 3000, it worked. Note that to run an application on port 80 you will need root privilege.
Error with the request: getaddrinfo EAI_AGAIN localhost:3000:80
Here is a complete code snippet
var http=require('http');
var options = {
protocol:'http:',
host: 'localhost',
port:3000,
path: '/iso/country/Japan',
method:'GET'
};
var callback = function(response) {
var str = '';
//another chunk of data has been recieved, so append it to `str`
response.on('data', function (chunk) {
str += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', function () {
console.log(str);
});
}
var request=http.request(options, callback);
request.on('error', function(err) {
// handle errors with the request itself
console.error('Error with the request:', err.message);
});
request.end();
I fixed this error with this
$ npm info express --verbose
# Error message: npm info retry will retry, error on last attempt: Error: getaddrinfo ENOTFOUND registry.npmjs.org registry.npmjs.org:443
$ nslookup registry.npmjs.org
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
registry.npmjs.org canonical name = a.sni.fastly.net.
a.sni.fastly.net canonical name = prod.a.sni.global.fastlylb.net.
Name: prod.a.sni.global.fastlylb.net
Address: 151.101.32.162
$ sudo vim /etc/hosts
# Add "151.101.32.162 registry.npmjs.org` to hosts file
$ npm info express --verbose
# Works now!
Original source: https://github.com/npm/npm/issues/6686
Note that this issue can also occur if the domain you are referencing goes down (EG. no longer exists.)
in my case error was because of using incorrect host value
was
var options = {
host: 'graph.facebook.com/v2.12/',
path: path
}
should be
var options = {
host: 'graph.facebook.com',
path: path
}
so anything after .com or .net etc should be moved to path parameter value
In my case the problem was a malformed URL.
I had double slashes in the URL.
I tried it using the request module, and was able to print the body of that page out pretty easily. Unfortunately with the skills I have, I can't help other than that.
I got this error when going from development environment to production environment. I was obsessed with putting https:// on all links. This is not necessary, so it may be a solution for some.
I was getting the same error and used below below link to get help:
https://nodejs.org/api/http.html#http_http_request_options_callback
I was not having in my code:
req.end();
(NodeJs V: 5.4.0)
once added above req.end(); line, I was able to get rid of the error and worked fine for me.
Try using the server IP address rather than the hostname.
This worked for me. Hope it will work for you too.
I got rid of http and extra slash(/).
I just used this 'node-test.herokuapp.com' and it worked.
If still you are facing checkout for proxy setting, for me it was the proxy setting which were missing and was not able to make the request as direct http/https are blocked. So i configured the proxy from my organization while making the request.
npm install https-proxy-agent
or
npm install http-proxy-agent
const httpsProxyAgent = require('https-proxy-agent');
const agent = new httpsProxyAgent("http://yourorganzation.proxy.url:8080");
const options = {
hostname: 'encrypted.google.com',
port: 443,
path: '/',
method: 'GET',
agent: agent
};
I got this issue resolved by removing non-desirable characters from the password for the connection. For example, I had these characters: <##% and it caused the problem (most probably hash tag was the root cause of the problem).
My problem was we were parsing url and generating http_options for http.request();
I was using request_url.host which already had port number with domain name so had to use request_url.hostname.
var request_url = new URL('http://example.org:4444/path');
var http_options = {};
http_options['hostname'] = request_url.hostname;//We were using request_url.host which includes port number
http_options['port'] = request_url.port;
http_options['path'] = request_url.pathname;
http_options['method'] = 'POST';
http_options['timeout'] = 3000;
http_options['rejectUnauthorized'] = false;

Resources