Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/koa/src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,8 @@ export class Request {
if (len === '') {
return;
}
return Number.parseInt(len);
const parsed = Number.parseInt(len, 10);
return Number.isNaN(parsed) ? undefined : parsed;
Comment thread
fengmk2 marked this conversation as resolved.
Comment on lines +331 to +332

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While Number.parseInt with a radix is an improvement, it is more lenient than the standard HTTP parsing expected for Content-Length. For example, Number.parseInt('10abc', 10) returns 10, whereas a strictly non-numeric value should ideally result in undefined. Additionally, if this.get returns an array of strings (which can happen in Node.js if multiple headers are present), Number.parseInt will stringify the array (e.g., '10,20') and return the first value, which is incorrect.

To align with the upstream Koa fix (koajs/koa#1961) and ensure stricter parsing, consider using Number() combined with Math.trunc().

Suggested change
const parsed = Number.parseInt(len, 10);
return Number.isNaN(parsed) ? undefined : parsed;
const parsed = Number(len);
return Number.isNaN(parsed) ? undefined : Math.trunc(parsed);

}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/koa/src/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export class Response {
*/
get length(): number | undefined {
if (this.has('Content-Length')) {
return Number.parseInt(this.get('Content-Length')) || 0;
return Number.parseInt(this.get('Content-Length'), 10) || 0;
}

const body = this.body;
Expand Down
36 changes: 36 additions & 0 deletions packages/koa/test/request/length.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,40 @@ describe('ctx.length', () => {
const req = request();
assert.strictEqual(req.length, undefined);
});

it('should handle zero content-length', () => {
const req = request();
req.header['content-length'] = '0';
assert.strictEqual(req.length, 0);
});

it('should handle Content-Length > 2GB (2147483648)', () => {
const req = request();
req.header['content-length'] = '2147483648';
assert.strictEqual(req.length, 2147483648);
});

it('should handle very large Content-Length (10GB)', () => {
const req = request();
req.header['content-length'] = '10000000000';
assert.strictEqual(req.length, 10000000000);
});

it('should handle floating-point-like strings (truncate decimal)', () => {
const req = request();
req.header['content-length'] = '10.5';
assert.strictEqual(req.length, 10);
});

it('should return undefined for non-numeric strings', () => {
const req = request();
req.header['content-length'] = 'invalid';
assert.strictEqual(req.length, undefined);
});

it('should return undefined for empty string', () => {
const req = request();
req.header['content-length'] = '';
assert.strictEqual(req.length, undefined);
});
Comment thread
fengmk2 marked this conversation as resolved.
});
Loading