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

File tree

4 files changed

+83
-80
lines changed

4 files changed

+83
-80
lines changed

.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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy