Skip to content

Commit

Permalink
fix: prefer IPv4 addresses when resolving domains
Browse files Browse the repository at this point in the history
Node 17+ changed the DNS resolution (see nodejs/node#40702), so now it resolves `localhost` according to the OS settings instead of IPv4-address first. The Karma server only listens on IPv4 address (127.0.0.1) by default, but the requests are sent to `localhost` in several places and `localhost` is resolved into IPv6 address (`::`) in Node 17+. So the run/stop/proxy request is unable to reach the Karma server and produces an error. This commit configures karma to use the IPv4-address first approach in newer Node version as well.

In the future major release, we may consider changing defaults to listen on IPv6 address instead, but IPv6 is not supported in Docker on macOS and Windows, so I think we should not rush such a change to make sure karma works there out of the box.

Fixes karma-runner#3730
  • Loading branch information
devoto13 committed May 11, 2022
1 parent a8e10b9 commit 3aa94fb
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 4 deletions.
6 changes: 5 additions & 1 deletion lib/middleware/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const { Agent: httpAgent } = require('http')
const { Agent: httpsAgent } = require('https')
const httpProxy = require('http-proxy')
const _ = require('lodash')
const { lookup } = require('../utils/dns-utils')

const log = require('../logger').create('proxy')

Expand Down Expand Up @@ -41,7 +42,10 @@ function parseProxyConfig (proxies, config) {
const port = proxyDetails.port || defaultPorts[proxyDetails.protocol] || config.port
const changeOrigin = proxyConfiguration.changeOrigin || false
const Agent = protocol === 'https:' ? httpsAgent : httpAgent
const agent = new Agent({ keepAlive: true })
const agent = new Agent({
keepAlive: true,
lookup
})
const proxy = httpProxy.createProxyServer({
target: { host: hostname, port, protocol },
xfwd: true,
Expand Down
4 changes: 3 additions & 1 deletion lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const EventEmitter = require('events').EventEmitter
const helper = require('./helper')
const cfg = require('./config')
const logger = require('./logger')
const { lookup } = require('./utils/dns-utils')
const log = logger.create('runner')

function parseExitCode (buffer, defaultExitCode, failOnEmptyTestSuite) {
Expand Down Expand Up @@ -74,7 +75,8 @@ function run (cliOptionsOrConfig, done) {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
},
lookup
}

const request = http.request(options, function (response) {
Expand Down
4 changes: 3 additions & 1 deletion lib/stopper.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const http = require('http')
const cfg = require('./config')
const logger = require('./logger')
const helper = require('./helper')
const { lookup } = require('./utils/dns-utils')

exports.stop = function (cliOptionsOrConfig, done) {
cliOptionsOrConfig = cliOptionsOrConfig || {}
Expand Down Expand Up @@ -42,7 +43,8 @@ exports.stop = function (cliOptionsOrConfig, done) {
hostname: config.hostname,
path: config.urlRoot + 'stop',
port: config.port,
method: 'GET'
method: 'GET',
lookup
})

request.on('response', function (response) {
Expand Down
11 changes: 11 additions & 0 deletions lib/utils/dns-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const dns = require('dns')

// Node >=17 has different DNS resolution (see
// https://github.com/nodejs/node/issues/40702), it resolves domains
// according to the OS settings instead of IPv4-address first. The Karma server
// only listens on IPv4 address (127.0.0.1) by default, but the requests are
// sent to `localhost` in several places and `localhost` is resolved into IPv6
// address (`::`). So the run/stop/proxy request is unable to reach the Karma
// server and produces an error. To mitigate this issue karma force the
// IPv4-address first approach in Node >=17 as well.
module.exports.lookup = (hostname, options, callback) => dns.lookup(hostname, { ...options, verbatim: false }, callback)
2 changes: 1 addition & 1 deletion test/e2e/support/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = class Proxy {
this.proxyPathRegExp = null

this.proxy = httpProxy.createProxyServer({
target: 'http://localhost:9876'
target: 'http://127.0.0.1:9876'
})

this.proxy.on('error', (err) => {
Expand Down

0 comments on commit 3aa94fb

Please sign in to comment.