mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 19:08:50 +00:00
fix: deviate from fetch() spec and allow status codes up to 999
This commit is contained in:
@@ -6559,7 +6559,7 @@ pub const NodeHTTPResponse = struct {
|
||||
if (status_code_value != .undefined) {
|
||||
break :brk globalObject.validateIntegerRange(status_code_value, i32, 200, .{
|
||||
.min = 100,
|
||||
.max = 599,
|
||||
.max = 999,
|
||||
}) catch return error.JSError;
|
||||
}
|
||||
|
||||
|
||||
@@ -714,11 +714,13 @@ pub const Response = struct {
|
||||
|
||||
if (response_init.fastGet(globalThis, .status)) |status_value| {
|
||||
const number = status_value.coerceToInt64(globalThis);
|
||||
if ((200 <= number and number < 600) or number == 101) {
|
||||
// Even though the fetch spec says the range is [200, 599], there are some websites
|
||||
// that use status codes up to 999, like linkedin.com, so allow it.
|
||||
if ((200 <= number and number <= 999) or number == 101) {
|
||||
result.status_code = @as(u16, @truncate(@as(u32, @intCast(number))));
|
||||
} else {
|
||||
if (!globalThis.hasException()) {
|
||||
const err = globalThis.createRangeErrorInstance("The status provided ({d}) must be 101 or in the range of [200, 599]", .{number});
|
||||
const err = globalThis.createRangeErrorInstance("The status provided ({d}) must be 101 or in the range of [200, 999]", .{number});
|
||||
return globalThis.throwValue(err);
|
||||
}
|
||||
return error.JSError;
|
||||
|
||||
@@ -303,7 +303,7 @@ describe.todoIf(isBroken && isIntelMacOS)(
|
||||
},
|
||||
);
|
||||
|
||||
[200, 200n, 303, 418, 599, 599n].forEach(statusCode => {
|
||||
[200, 200n, 303, 418, 599, 599n, 999, 999n].forEach(statusCode => {
|
||||
it(`should response with HTTP status code (${statusCode})`, async () => {
|
||||
await runTest(
|
||||
{
|
||||
@@ -320,7 +320,7 @@ describe.todoIf(isBroken && isIntelMacOS)(
|
||||
});
|
||||
});
|
||||
|
||||
[-200, 42, 100, 102, 12345, Math.PI, 999, 600, 199, 199n, 600n, 100n, 102n].forEach(statusCode => {
|
||||
[-200, 42, 100, 102, 12345, Math.PI, 199, 199n, 100n, 102n].forEach(statusCode => {
|
||||
it(`should error on invalid HTTP status code (${statusCode})`, async () => {
|
||||
await runTest(
|
||||
{
|
||||
|
||||
90
test/js/node/test/parallel/test-http-response-statuscode.js
Normal file
90
test/js/node/test/parallel/test-http-response-statuscode.js
Normal file
@@ -0,0 +1,90 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const http = require('http');
|
||||
const Countdown = require('../common/countdown');
|
||||
|
||||
const MAX_REQUESTS = 13;
|
||||
let reqNum = 0;
|
||||
|
||||
function test(res, header, code) {
|
||||
assert.throws(() => {
|
||||
res.writeHead(header);
|
||||
}, {
|
||||
code: 'ERR_HTTP_INVALID_STATUS_CODE',
|
||||
name: 'RangeError',
|
||||
message: `Invalid status code: ${code}`
|
||||
});
|
||||
}
|
||||
|
||||
const server = http.Server(common.mustCall(function(req, res) {
|
||||
switch (reqNum) {
|
||||
case 0:
|
||||
test(res, -1, '-1');
|
||||
break;
|
||||
case 1:
|
||||
test(res, Infinity, 'Infinity');
|
||||
break;
|
||||
case 2:
|
||||
test(res, NaN, 'NaN');
|
||||
break;
|
||||
case 3:
|
||||
test(res, {}, '{}');
|
||||
break;
|
||||
case 4:
|
||||
test(res, 99, '99');
|
||||
break;
|
||||
case 5:
|
||||
test(res, 1000, '1000');
|
||||
break;
|
||||
case 6:
|
||||
test(res, '1000', '"1000"');
|
||||
break;
|
||||
case 7:
|
||||
test(res, null, 'null');
|
||||
break;
|
||||
case 8:
|
||||
test(res, true, 'true');
|
||||
break;
|
||||
case 9:
|
||||
test(res, [], '[]');
|
||||
break;
|
||||
case 10:
|
||||
test(res, 'this is not valid', '"this is not valid"');
|
||||
break;
|
||||
case 11:
|
||||
test(res, '404 this is not valid either', '"404 this is not valid either"');
|
||||
break;
|
||||
case 12:
|
||||
assert.throws(() => { res.writeHead(); },
|
||||
{
|
||||
code: 'ERR_HTTP_INVALID_STATUS_CODE',
|
||||
name: 'RangeError',
|
||||
message: 'Invalid status code: undefined'
|
||||
});
|
||||
this.close();
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unexpected request');
|
||||
}
|
||||
res.statusCode = 200;
|
||||
res.end();
|
||||
}, MAX_REQUESTS));
|
||||
server.listen();
|
||||
|
||||
const countdown = new Countdown(MAX_REQUESTS, () => server.close());
|
||||
|
||||
server.on('listening', function makeRequest() {
|
||||
http.get({
|
||||
port: this.address().port
|
||||
}, (res) => {
|
||||
assert.strictEqual(res.statusCode, 200);
|
||||
res.on('end', () => {
|
||||
countdown.dec();
|
||||
reqNum = MAX_REQUESTS - countdown.remaining;
|
||||
if (countdown.remaining > 0)
|
||||
makeRequest.call(this);
|
||||
});
|
||||
res.resume();
|
||||
});
|
||||
});
|
||||
@@ -1331,12 +1331,12 @@ describe("Response", () => {
|
||||
it("should work with bigint", () => {
|
||||
var r = new Response("hello status", { status: 200n });
|
||||
expect(r.status).toBe(200);
|
||||
r = new Response("hello status", { status: 599n });
|
||||
expect(r.status).toBe(599);
|
||||
r = new Response("hello status", { status: 999n });
|
||||
expect(r.status).toBe(999);
|
||||
r = new Response("hello status", { status: BigInt(200) });
|
||||
expect(r.status).toBe(200);
|
||||
r = new Response("hello status", { status: BigInt(599) });
|
||||
expect(r.status).toBe(599);
|
||||
r = new Response("hello status", { status: BigInt(999) });
|
||||
expect(r.status).toBe(999);
|
||||
});
|
||||
testBlobInterface(data => new Response(data), true);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user