Node.js Https request Error

I've tried the sample from the documentation and it works great.

But when I change the URL to https://api.mercadolibre.com/sites/, the request hangs. The only thing I get is:

{ [Error: socket hang up] code: 'ECONNRESET' }

Here's my code:

var https = require('https');

this.dispatch = function(req, res) {
  var renderHtml = function(content) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end(content, 'utf-8');
  }

  var parts = req.url.split('/');

  var options = {
    host: 'api.mercadolibre.com',
    port: 443,
    path: '/sites/',
    method: 'GET'
  };

  var request = https.request(options, function(res) {
    console.log("statusCode: ", res.statusCode);
    console.log("headers: ", res.headers);

    res.on('data', function(d) {
      process.stdout.write(d);
    });
  });

  request.on('error', function(e) {
    console.error('error');
    console.error(e);
  });

  request.end();
  return 'item id:' + parts[2];
};

I've tried with curl, soapui and with a browser. On all cases works great, but with node.js it doesn't.

How can I get more data on what's going on?

added

With curl i do: curl --sslv3 https://api.mercadolibre.com/sites/ works. I've test same in centos 6 and works too. I've reinstalled node, this time from source, same problem. My Os is ubuntu 12.04. Thanks.

I'm not sure about api.mercadolibre.com site, but I can call API if I remove port param, like following code:

var options = {
    host: 'api.mercadolibre.com',
    path: '/sites/',
    method: 'GET'
};

And we also need add param to support SSL version 3:

https.globalAgent.options.secureProtocol = 'SSLv3_method';

Since it is working with curl, try using node-curl module. I lost a whole day trying to make it work in node.js with http and/or https modules until I switched to node-curl.

Try this:

var curl = require('node-curl');
curl('https://api.mercadolibre.com/sites/', {SSLVERSION: 3}, function(err, res) {
    var body = res.body;
    res.close();
    console.log(body);
});

Why not use a library like request to deal with the details for you?

var request = require('request');

request('https://api.mercadolibre.com/sites/', {}, function(err, res, body) {
  console.log("Got body: ", body);
});

This yields:

Got body:  [{"id":"MLA","name":"Argentina"},{"id":"MLB","name":"Brasil"},{"id":"MCO","name":"Colombia"},{"id":"MCR","name":"Costa Rica"},{"id":"MEC","name":"Ecuador"},{"id":"MLC","name":"Chile"},{"id":"MLM","name":"Mexico"},{"id":"MLU","name":"Uruguay"},{"id":"MLV","name":"Venezuela"},{"id":"MPA","name":"Panamá"},{"id":"MPE","name":"Perú"},{"id":"MPT","name":"Portugal"},{"id":"MRD","name":"Dominicana"}]

Same here, working with curl but not with node.js.

Problem: here on CentOS-5 curl usesthe provides openssl libraries and so uses centos standard /etc/pki/tls/certs/ca-bundle.crt for CA checks.

Where does node.js look for?, via strace there I cannot see any reference to a CA-file for checking. Node.js request against server with valid SSL-certificate from well known old issuer are accepted, but not against my own webserver with own CA. I put my own CA.crt in the ca-bundle.crt file, so now curl accepts it, but not node.js.

Only solution for now is to deactivate the verification-check for my dev-box:

    var client = require('https');
    var download_options = url.parse(sourceUrl);
    download_options.method = "GET";
    download_options.agent = false;
    download_options.rejectUnauthorized = false; / HERE to accept all SSL-certificates */

    var download_request = client.request(download_options);

I think you are behind a proxy which you need to specify to request. Proxy settings are detected automatically by libcurl, which node-curl uses. Therefore the request passes in node-curl.

Therefore, find out the proxy IP and port your organization uses, and try this:

var request = require('request');
request({
    uri : 'https://mail.google.com/mail',
    proxy : 'http://<proxy ip>:<proxy port>'
}, function (error, response, body) {
    if (!error && response.statusCode == 200) {
        console.log(body) // Print the google web page.
    }else{
        console.log(error);
        console.log(response.statusCode);
    }
})

You will get the ECONNRESET error if you do this:

post_options.path = 'history';
...
var req = http.request(post_options, function(res) {
...

That is, you need to make sure your path has a / like this:

post_options.path = '/history';
...