mirror of
https://github.com/tenrok/axios.git
synced 2026-06-17 19:21:29 +03:00
fix: enforce max body length when max redirects is 0 (#10753)
This commit is contained in:
+35
-1
@@ -967,7 +967,41 @@ export default isHttpAdapterSupported &&
|
||||
}
|
||||
});
|
||||
|
||||
data.pipe(req);
|
||||
// Enforce maxBodyLength for streamed uploads on the native http/https
|
||||
// transport (maxRedirects === 0); follow-redirects enforces it on the
|
||||
// other path. See GHSA-5c9x-8gcm-mpgx.
|
||||
let uploadStream = data;
|
||||
if (config.maxBodyLength > -1 && config.maxRedirects === 0) {
|
||||
const limit = config.maxBodyLength;
|
||||
let bytesSent = 0;
|
||||
uploadStream = stream.pipeline(
|
||||
[
|
||||
data,
|
||||
new stream.Transform({
|
||||
transform(chunk, _enc, cb) {
|
||||
bytesSent += chunk.length;
|
||||
if (bytesSent > limit) {
|
||||
return cb(
|
||||
new AxiosError(
|
||||
'Request body larger than maxBodyLength limit',
|
||||
AxiosError.ERR_BAD_REQUEST,
|
||||
config,
|
||||
req
|
||||
)
|
||||
);
|
||||
}
|
||||
cb(null, chunk);
|
||||
},
|
||||
}),
|
||||
],
|
||||
utils.noop
|
||||
);
|
||||
uploadStream.on('error', (err) => {
|
||||
if (!req.destroyed) req.destroy(err);
|
||||
});
|
||||
}
|
||||
|
||||
uploadStream.pipe(req);
|
||||
} else {
|
||||
data && req.write(data);
|
||||
req.end();
|
||||
|
||||
@@ -988,6 +988,82 @@ describe('supports http with nodejs', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('should enforce maxBodyLength for streamed uploads with maxRedirects: 0 (GHSA-5c9x-8gcm-mpgx)', async () => {
|
||||
let bytesReceived = 0;
|
||||
const server = await startHTTPServer(
|
||||
(req, res) => {
|
||||
req.on('data', (chunk) => {
|
||||
bytesReceived += chunk.length;
|
||||
});
|
||||
req.on('end', () => {
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ received: bytesReceived }));
|
||||
});
|
||||
},
|
||||
{ port: SERVER_PORT }
|
||||
);
|
||||
|
||||
try {
|
||||
const size = 2 * 1024 * 1024;
|
||||
const buf = Buffer.alloc(size, 0x61);
|
||||
const source = stream.Readable.from([buf]);
|
||||
|
||||
await assert.rejects(
|
||||
axios.post(`http://localhost:${server.address().port}/`, source, {
|
||||
maxBodyLength: 1024,
|
||||
maxRedirects: 0,
|
||||
headers: { 'Content-Type': 'application/octet-stream' },
|
||||
}),
|
||||
(error) => {
|
||||
assert.strictEqual(error.message, 'Request body larger than maxBodyLength limit');
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
bytesReceived <= 1024 * 4,
|
||||
`server should not receive full payload; got ${bytesReceived}`
|
||||
);
|
||||
} finally {
|
||||
await stopHTTPServer(server);
|
||||
}
|
||||
});
|
||||
|
||||
it('should allow streamed uploads under maxBodyLength with maxRedirects: 0', async () => {
|
||||
let bytesReceived = 0;
|
||||
const server = await startHTTPServer(
|
||||
(req, res) => {
|
||||
req.on('data', (chunk) => {
|
||||
bytesReceived += chunk.length;
|
||||
});
|
||||
req.on('end', () => {
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ received: bytesReceived }));
|
||||
});
|
||||
},
|
||||
{ port: SERVER_PORT }
|
||||
);
|
||||
|
||||
try {
|
||||
const payload = Buffer.alloc(512, 0x62);
|
||||
const source = stream.Readable.from([payload]);
|
||||
|
||||
const response = await axios.post(
|
||||
`http://localhost:${server.address().port}/`,
|
||||
source,
|
||||
{
|
||||
maxBodyLength: 1024,
|
||||
maxRedirects: 0,
|
||||
headers: { 'Content-Type': 'application/octet-stream' },
|
||||
}
|
||||
);
|
||||
|
||||
assert.strictEqual(response.data.received, payload.length);
|
||||
} finally {
|
||||
await stopHTTPServer(server);
|
||||
}
|
||||
});
|
||||
|
||||
it('should properly support default max body length (follow-redirects as well)', async () => {
|
||||
// Taken from follow-redirects defaults.
|
||||
const followRedirectsMaxBodyDefaults = 10 * 1024 * 1024;
|
||||
|
||||
Reference in New Issue
Block a user