Skip to content

Commit

Permalink
chore(tests): fixed tests to pass in node v19 and v20 with `keep-aliv…
Browse files Browse the repository at this point in the history
…e` enabled; (#6021)
  • Loading branch information
DigitalBrainJS committed Oct 22, 2023
1 parent 5aaff53 commit 7d45ab2
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 80 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Expand Up @@ -15,7 +15,7 @@ jobs:

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

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion lib/adapters/http.js
Expand Up @@ -580,7 +580,7 @@ export default isHttpAdapterSupported && function httpAdapter(config) {
}
response.data = responseData;
} catch (err) {
reject(AxiosError.from(err, null, config, response.request, response));
return reject(AxiosError.from(err, null, config, response.request, response));
}
settle(resolve, reject, response);
});
Expand Down
154 changes: 77 additions & 77 deletions test/unit/adapters/http.js
Expand Up @@ -58,14 +58,15 @@ const LOCAL_SERVER_URL = 'http://localhost:4444';

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

function startHTTPServer(options) {
function startHTTPServer(handlerOrOptions, options) {

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

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

Expand Down Expand Up @@ -93,9 +94,21 @@ function startHTTPServer(options) {
}).listen(port, function (err) {
err ? reject(err) : resolve(this);
});

server.keepAliveTimeout = keepAlive;
});
}

const stopHTTPServer = async (server, timeout = 10000) => {
if (server) {
if (typeof server.closeAllConnections === 'function') {
server.closeAllConnections();
}

await Promise.race([new Promise(resolve => server.close(resolve)), setTimeoutAsync(timeout)]);
}
}

const handleFormData = (req) => {
return new Promise((resolve, reject) => {
const form = new formidable.IncomingForm();
Expand Down Expand Up @@ -131,16 +144,12 @@ function generateReadableStream(length = 1024 * 1024, chunkSize = 10 * 1024, sle
}

describe('supports http with nodejs', function () {
afterEach(async function () {
await Promise.all([stopHTTPServer(server), stopHTTPServer(proxy)]);

server = null;
proxy = null;

afterEach(function () {
if (server) {
server.close();
server = null;
}
if (proxy) {
proxy.close();
proxy = null;
}
delete process.env.http_proxy;
delete process.env.https_proxy;
delete process.env.no_proxy;
Expand Down Expand Up @@ -382,53 +391,57 @@ describe('supports http with nodejs', function () {
});
});

it('should support beforeRedirect and proxy with redirect', function (done) {
var requestCount = 0;
var totalRedirectCount = 5;
server = http.createServer(function (req, res) {
it('should support beforeRedirect and proxy with redirect', async () => {
let requestCount = 0;
let totalRedirectCount = 5;

server = await startHTTPServer(function (req, res) {
requestCount += 1;
if (requestCount <= totalRedirectCount) {
res.setHeader('Location', 'http://localhost:4444');
res.writeHead(302);
}
res.end();
}).listen(4444, function () {
var proxyUseCount = 0;
proxy = http.createServer(function (request, response) {
proxyUseCount += 1;
var parsed = url.parse(request.url);
var opts = {
host: parsed.hostname,
port: parsed.port,
path: parsed.path
};
}, {port: 4444});

let proxyUseCount = 0;
proxy = await startHTTPServer(function (req, res) {
proxyUseCount += 1;
const targetUrl = new URL(req.url, 'http://' + req.headers.host);
const opts = {
host: targetUrl.hostname,
port: targetUrl.port,
path: targetUrl.path,
method: req.method
};

http.get(opts, function (res) {
response.writeHead(res.statusCode, res.headers);
res.on('data', function (data) {
response.write(data)
});
res.on('end', function () {
response.end();
});
});
}).listen(4000, function () {
var configBeforeRedirectCount = 0;
axios.get('http://localhost:4444/', {
proxy: {
host: 'localhost',
port: 4000
},
maxRedirects: totalRedirectCount,
beforeRedirect: function (options) {
configBeforeRedirectCount += 1;
}
}).then(function (res) {
assert.equal(totalRedirectCount, configBeforeRedirectCount, 'should invoke config.beforeRedirect option on every redirect');
assert.equal(totalRedirectCount + 1, proxyUseCount, 'should go through proxy on every redirect');
done();
}).catch(done);
const request = http.get(opts, function (response) {
res.writeHead(response.statusCode, response.headers);
stream.pipeline(response, res, () => {});
});

request.on('error', (err) => {
console.warn('request error', err);
res.statusCode = 500;
res.end();
})

}, {port: 4000});

let configBeforeRedirectCount = 0;

await axios.get('http://localhost:4444/', {
proxy: {
host: 'localhost',
port: 4000
},
maxRedirects: totalRedirectCount,
beforeRedirect: function (options) {
configBeforeRedirectCount += 1;
}
}).then(function (res) {
assert.equal(totalRedirectCount, configBeforeRedirectCount, 'should invoke config.beforeRedirect option on every redirect');
assert.equal(totalRedirectCount + 1, proxyUseCount, 'should go through proxy on every redirect');
});
});

Expand Down Expand Up @@ -666,31 +679,18 @@ describe('supports http with nodejs', function () {
});
});

it('should support max content length', function (done) {
var str = Array(100000).join('ж');

server = http.createServer(function (req, res) {
it('should support max content length', async function () {
server = await startHTTPServer(function (req, res) {
res.setHeader('Content-Type', 'text/html; charset=UTF-8');
res.end(str);
}).listen(4444, function () {
var success = false, failure = false, error;
res.end(Array(5000).join('#'));
}, {port: 4444});

axios.get('http://localhost:4444/', {
maxContentLength: 2000
}).then(function (res) {
success = true;
}).catch(function (err) {
error = err;
failure = true;
});

setTimeout(function () {
assert.equal(success, false, 'request should not succeed');
assert.equal(failure, true, 'request should fail');
assert.equal(error.message, 'maxContentLength size of 2000 exceeded');
done();
}, 100);
});
await assert.rejects(() => {
return axios.get('http://localhost:4444/', {
maxContentLength: 2000,
maxRedirects: 0
})
},/maxContentLength size of 2000 exceeded/);
});

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

axios.get('http://localhost:4444/one', {
maxContentLength: 2000
maxContentLength: 2000,
}).then(function (res) {
success = true;
}).catch(function (err) {
Expand Down
5 changes: 4 additions & 1 deletion test/unit/regression/SNYK-JS-AXIOS-1038255.js
Expand Up @@ -20,8 +20,9 @@ describe('Server-Side Request Forgery (SSRF)', () => {
fail = true;
res.end('rm -rf /');
}).listen(EVIL_PORT);

proxy = http.createServer(function (req, res) {
if (req.url === 'http://localhost:' + EVIL_PORT + '/') {
if (new URL(req.url, 'http://' + req.headers.host).toString() === 'http://localhost:' + EVIL_PORT + '/') {
return res.end(JSON.stringify({
msg: 'Protected',
headers: req.headers,
Expand All @@ -35,8 +36,10 @@ describe('Server-Side Request Forgery (SSRF)', () => {
server.close();
proxy.close();
});

it('obeys proxy settings when following redirects', async () => {
location = 'http://localhost:' + EVIL_PORT;

let response = await axios({
method: "get",
url: "http://www.google.com/",
Expand Down

0 comments on commit 7d45ab2

Please sign in to comment.