Skip to content

HTTP and HTTPS attempt only single IP, causing intermittent failures #708

Closed
@jsha

Description

@jsha

Steps to reproduce:

Find a host that answers a given port only on some of the returned IP addresses for its name. For instance, www.itunes.com has this problem. Then run this code:

require('https').get('https://www.itunes.com', function(res) {
  console.log('statusCode:', res.statusCode);
}).on('error', function(err) {
  console.log('Error:', err);
});

Since www.itunes.com resolves to three different IP addresses (see dig www.itunes.com) in random order, io.js will connect to a random host each time, sometimes failing and sometimes succeeding.

Arguably, this is broken behavior on the part of the host. However, it's reasonably common on the web. Firefox and Chrome each attempt parallel connections to all IP addresses provided in the DNS response, using the first connection to succeed. Curl attempts each IP address in sequence until it gets a successful connection or runs out of IP addresses: https://github.com/bagder/curl/blob/master/lib/connect.c#L1156

It looks like the io.js http and https libraries, through Agent, call into Socket.connect, which uses dns.lookup (returns just one IP address) instead of dns.resolve: https://github.com/iojs/io.js/blob/v1.x/lib/net.js#L900.

Is it practical to change the Socket.connect behavior to use dns.resolve and try multiple IP addresses? I'm guessing that would be a fairly API-incompatible change. Another possibility: Agent could implement failure handling code that specifically catched connection refused and timeout errors, calls dns.resolve itself, and calls Socket.connect again with IP address arguments. This would be less performant but also a smaller API change.

For the real-world motivating example, I ran into this when writing automated tests for HTTPS Everywhere's rulesets: https://github.com/jsha/https-everywhere/blob/rules-tester/rewriter/tester.js. As-is, I get a number of false positives from hosts that appear to fail but actual work fine in a browser.

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues with confirmed bugs.feature requestIssues that request new features to be added to Node.js.httpIssues or PRs related to the http subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions