Skip to content

Commit 7d45ab2

Browse files
chore(tests): fixed tests to pass in node v19 and v20 with keep-alive enabled; (#6021)
1 parent 5aaff53 commit 7d45ab2

4 files changed

Lines changed: 83 additions & 80 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515

1616
strategy:
1717
matrix:
18-
node-version: [12.x, 14.x, 16.x, 18.x]
18+
node-version: [12.x, 14.x, 16.x, 18.x, 20.x]
1919

2020
steps:
2121
- uses: actions/checkout@v3

lib/adapters/http.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ export default isHttpAdapterSupported && function httpAdapter(config) {
580580
}
581581
response.data = responseData;
582582
} catch (err) {
583-
reject(AxiosError.from(err, null, config, response.request, response));
583+
return reject(AxiosError.from(err, null, config, response.request, response));
584584
}
585585
settle(resolve, reject, response);
586586
});

test/unit/adapters/http.js

Lines changed: 77 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,15 @@ const LOCAL_SERVER_URL = 'http://localhost:4444';
5858

5959
const SERVER_HANDLER_STREAM_ECHO = (req, res) => req.pipe(res);
6060

61-
function startHTTPServer(options) {
61+
function startHTTPServer(handlerOrOptions, options) {
6262

63-
const {handler, useBuffering = false, rate = undefined, port = 4444} = typeof options === 'function' ? {
64-
handler: options
65-
} : options || {};
63+
const {handler, useBuffering = false, rate = undefined, port = 4444, keepAlive = 1000} =
64+
Object.assign(typeof handlerOrOptions === 'function' ? {
65+
handler: handlerOrOptions
66+
} : handlerOrOptions || {}, options);
6667

6768
return new Promise((resolve, reject) => {
68-
http.createServer(handler || async function (req, res) {
69+
const server = http.createServer(handler || async function (req, res) {
6970
try {
7071
req.headers['content-length'] && res.setHeader('content-length', req.headers['content-length']);
7172

@@ -93,9 +94,21 @@ function startHTTPServer(options) {
9394
}).listen(port, function (err) {
9495
err ? reject(err) : resolve(this);
9596
});
97+
98+
server.keepAliveTimeout = keepAlive;
9699
});
97100
}
98101

102+
const stopHTTPServer = async (server, timeout = 10000) => {
103+
if (server) {
104+
if (typeof server.closeAllConnections === 'function') {
105+
server.closeAllConnections();
106+
}
107+
108+
await Promise.race([new Promise(resolve => server.close(resolve)), setTimeoutAsync(timeout)]);
109+
}
110+
}
111+
99112
const handleFormData = (req) => {
100113
return new Promise((resolve, reject) => {
101114
const form = new formidable.IncomingForm();
@@ -131,16 +144,12 @@ function generateReadableStream(length = 1024 * 1024, chunkSize = 10 * 1024, sle
131144
}
132145

133146
describe('supports http with nodejs', function () {
147+
afterEach(async function () {
148+
await Promise.all([stopHTTPServer(server), stopHTTPServer(proxy)]);
149+
150+
server = null;
151+
proxy = null;
134152

135-
afterEach(function () {
136-
if (server) {
137-
server.close();
138-
server = null;
139-
}
140-
if (proxy) {
141-
proxy.close();
142-
proxy = null;
143-
}
144153
delete process.env.http_proxy;
145154
delete process.env.https_proxy;
146155
delete process.env.no_proxy;
@@ -382,53 +391,57 @@ describe('supports http with nodejs', function () {
382391
});
383392
});
384393

385-
it('should support beforeRedirect and proxy with redirect', function (done) {
386-
var requestCount = 0;
387-
var totalRedirectCount = 5;
388-
server = http.createServer(function (req, res) {
394+
it('should support beforeRedirect and proxy with redirect', async () => {
395+
let requestCount = 0;
396+
let totalRedirectCount = 5;
397+
398+
server = await startHTTPServer(function (req, res) {
389399
requestCount += 1;
390400
if (requestCount <= totalRedirectCount) {
391401
res.setHeader('Location', 'http://localhost:4444');
392402
res.writeHead(302);
393403
}
394404
res.end();
395-
}).listen(4444, function () {
396-
var proxyUseCount = 0;
397-
proxy = http.createServer(function (request, response) {
398-
proxyUseCount += 1;
399-
var parsed = url.parse(request.url);
400-
var opts = {
401-
host: parsed.hostname,
402-
port: parsed.port,
403-
path: parsed.path
404-
};
405+
}, {port: 4444});
406+
407+
let proxyUseCount = 0;
408+
proxy = await startHTTPServer(function (req, res) {
409+
proxyUseCount += 1;
410+
const targetUrl = new URL(req.url, 'http://' + req.headers.host);
411+
const opts = {
412+
host: targetUrl.hostname,
413+
port: targetUrl.port,
414+
path: targetUrl.path,
415+
method: req.method
416+
};
405417

406-
http.get(opts, function (res) {
407-
response.writeHead(res.statusCode, res.headers);
408-
res.on('data', function (data) {
409-
response.write(data)
410-
});
411-
res.on('end', function () {
412-
response.end();
413-
});
414-
});
415-
}).listen(4000, function () {
416-
var configBeforeRedirectCount = 0;
417-
axios.get('http://localhost:4444/', {
418-
proxy: {
419-
host: 'localhost',
420-
port: 4000
421-
},
422-
maxRedirects: totalRedirectCount,
423-
beforeRedirect: function (options) {
424-
configBeforeRedirectCount += 1;
425-
}
426-
}).then(function (res) {
427-
assert.equal(totalRedirectCount, configBeforeRedirectCount, 'should invoke config.beforeRedirect option on every redirect');
428-
assert.equal(totalRedirectCount + 1, proxyUseCount, 'should go through proxy on every redirect');
429-
done();
430-
}).catch(done);
418+
const request = http.get(opts, function (response) {
419+
res.writeHead(response.statusCode, response.headers);
420+
stream.pipeline(response, res, () => {});
431421
});
422+
423+
request.on('error', (err) => {
424+
console.warn('request error', err);
425+
res.statusCode = 500;
426+
res.end();
427+
})
428+
429+
}, {port: 4000});
430+
431+
let configBeforeRedirectCount = 0;
432+
433+
await axios.get('http://localhost:4444/', {
434+
proxy: {
435+
host: 'localhost',
436+
port: 4000
437+
},
438+
maxRedirects: totalRedirectCount,
439+
beforeRedirect: function (options) {
440+
configBeforeRedirectCount += 1;
441+
}
442+
}).then(function (res) {
443+
assert.equal(totalRedirectCount, configBeforeRedirectCount, 'should invoke config.beforeRedirect option on every redirect');
444+
assert.equal(totalRedirectCount + 1, proxyUseCount, 'should go through proxy on every redirect');
432445
});
433446
});
434447

@@ -666,31 +679,18 @@ describe('supports http with nodejs', function () {
666679
});
667680
});
668681

669-
it('should support max content length', function (done) {
670-
var str = Array(100000).join('ж');
671-
672-
server = http.createServer(function (req, res) {
682+
it('should support max content length', async function () {
683+
server = await startHTTPServer(function (req, res) {
673684
res.setHeader('Content-Type', 'text/html; charset=UTF-8');
674-
res.end(str);
675-
}).listen(4444, function () {
676-
var success = false, failure = false, error;
685+
res.end(Array(5000).join('#'));
686+
}, {port: 4444});
677687

678-
axios.get('http://localhost:4444/', {
679-
maxContentLength: 2000
680-
}).then(function (res) {
681-
success = true;
682-
}).catch(function (err) {
683-
error = err;
684-
failure = true;
685-
});
686-
687-
setTimeout(function () {
688-
assert.equal(success, false, 'request should not succeed');
689-
assert.equal(failure, true, 'request should fail');
690-
assert.equal(error.message, 'maxContentLength size of 2000 exceeded');
691-
done();
692-
}, 100);
693-
});
688+
await assert.rejects(() => {
689+
return axios.get('http://localhost:4444/', {
690+
maxContentLength: 2000,
691+
maxRedirects: 0
692+
})
693+
},/maxContentLength size of 2000 exceeded/);
694694
});
695695

696696
it('should support max content length for redirected', function (done) {
@@ -711,7 +711,7 @@ describe('supports http with nodejs', function () {
711711
var success = false, failure = false, error;
712712

713713
axios.get('http://localhost:4444/one', {
714-
maxContentLength: 2000
714+
maxContentLength: 2000,
715715
}).then(function (res) {
716716
success = true;
717717
}).catch(function (err) {

test/unit/regression/SNYK-JS-AXIOS-1038255.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ describe('Server-Side Request Forgery (SSRF)', () => {
2020
fail = true;
2121
res.end('rm -rf /');
2222
}).listen(EVIL_PORT);
23+
2324
proxy = http.createServer(function (req, res) {
24-
if (req.url === 'http://localhost:' + EVIL_PORT + '/') {
25+
if (new URL(req.url, 'http://' + req.headers.host).toString() === 'http://localhost:' + EVIL_PORT + '/') {
2526
return res.end(JSON.stringify({
2627
msg: 'Protected',
2728
headers: req.headers,
@@ -35,8 +36,10 @@ describe('Server-Side Request Forgery (SSRF)', () => {
3536
server.close();
3637
proxy.close();
3738
});
39+
3840
it('obeys proxy settings when following redirects', async () => {
3941
location = 'http://localhost:' + EVIL_PORT;
42+
4043
let response = await axios({
4144
method: "get",
4245
url: "http://www.google.com/",

0 commit comments

Comments
 (0)