aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/bun.js/api/server.zig75
-rw-r--r--test/bun.js/serve.test.ts80
2 files changed, 153 insertions, 2 deletions
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig
index 531d4830b..ebe27f6e1 100644
--- a/src/bun.js/api/server.zig
+++ b/src/bun.js/api/server.zig
@@ -470,6 +470,77 @@ pub const ServerConfig = struct {
}
};
+const HTTPStatusText = struct {
+ pub fn get(code: u16) ?[]const u8 {
+ return switch (code) {
+ 100 => "100 Continue",
+ 101 => "101 Switching protocols",
+ 102 => "102 Processing",
+ 103 => "103 Early Hints",
+ 200 => "200 OK",
+ 201 => "201 Created",
+ 202 => "202 Accepted",
+ 203 => "203 Non-Authoritative Information",
+ 204 => "204 No Content",
+ 205 => "205 Reset Content",
+ 206 => "206 Partial Content",
+ 207 => "207 Multi-Status",
+ 208 => "208 Already Reported",
+ 226 => "226 IM Used",
+ 300 => "300 Multiple Choices",
+ 301 => "301 Moved Permanently",
+ 302 => "302 Found",
+ 303 => "303 See Other",
+ 304 => "304 Not Modified",
+ 305 => "305 Use Proxy",
+ 306 => "306 Switch Proxy",
+ 307 => "307 Temporary Redirect",
+ 308 => "308 Permanent Redirect",
+ 400 => "400 Bad Request",
+ 401 => "401 Unauthorized",
+ 402 => "402 Payment Required",
+ 403 => "403 Forbidden",
+ 404 => "404 Not Found",
+ 405 => "405 Method Not Allowed",
+ 406 => "406 Not Acceptable",
+ 407 => "407 Proxy Authentication Required",
+ 408 => "408 Request Timeout",
+ 409 => "409 Conflict",
+ 410 => "410 Gone",
+ 411 => "411 Length Required",
+ 412 => "412 Precondition Failed",
+ 413 => "413 Payload Too Large",
+ 414 => "414 URI Too Long",
+ 415 => "415 Unsupported Media Type",
+ 416 => "416 Range Not Satisfiable",
+ 417 => "417 Expectation Failed",
+ 418 => "418 I'm a Teapot",
+ 421 => "421 Misdirected Request",
+ 422 => "422 Unprocessable Entity",
+ 423 => "423 Locked",
+ 424 => "424 Failed Dependency",
+ 425 => "425 Too Early",
+ 426 => "426 Upgrade Required",
+ 428 => "428 Precondition Required",
+ 429 => "429 Too Many Requests",
+ 431 => "431 Request Header Fields Too Large",
+ 451 => "451 Unavailable For Legal Reasons",
+ 500 => "500 Internal Server Error",
+ 501 => "501 Not Implemented",
+ 502 => "502 Bad Gateway",
+ 503 => "503 Service Unavailable",
+ 504 => "504 Gateway Timeout",
+ 505 => "505 HTTP Version Not Supported",
+ 506 => "506 Variant Also Negotiates",
+ 507 => "507 Insufficient Storage",
+ 508 => "508 Loop Detected",
+ 510 => "510 Not Extended",
+ 511 => "511 Network Authentication Required",
+ else => null,
+ };
+ }
+};
+
pub fn NewRequestContextStackAllocator(comptime RequestContext: type, comptime count: usize) type {
// Pre-allocate up to 2048 requests
// use a bitset to track which ones are used
@@ -1006,8 +1077,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
std.debug.assert(!this.has_written_status);
this.has_written_status = true;
- if (status == 302) {
- this.resp.writeStatus("302 Found");
+ if (HTTPStatusText.get(status)) |text| {
+ this.resp.writeStatus(text);
} else {
this.resp.writeStatus(std.fmt.bufPrint(&status_text_buf, "{d} HM", .{status}) catch unreachable);
}
diff --git a/test/bun.js/serve.test.ts b/test/bun.js/serve.test.ts
index ea175dca5..91b57a738 100644
--- a/test/bun.js/serve.test.ts
+++ b/test/bun.js/serve.test.ts
@@ -598,3 +598,83 @@ it("should support reloading", async () => {
expect(await response2.text()).toBe("second");
server.stop();
});
+
+describe("status code text", () => {
+ const fixture = {
+ 200: "OK",
+ 201: "Created",
+ 202: "Accepted",
+ 203: "Non-Authoritative Information",
+ 204: "No Content",
+ 205: "Reset Content",
+ 206: "Partial Content",
+ 207: "Multi-Status",
+ 208: "Already Reported",
+ 226: "IM Used",
+ 300: "Multiple Choices",
+ 301: "Moved Permanently",
+ 302: "Found",
+ 303: "See Other",
+ 304: "Not Modified",
+ 305: "Use Proxy",
+ 306: "Switch Proxy",
+ 307: "Temporary Redirect",
+ 308: "Permanent Redirect",
+ 400: "Bad Request",
+ 401: "Unauthorized",
+ 402: "Payment Required",
+ 403: "Forbidden",
+ 404: "Not Found",
+ 405: "Method Not Allowed",
+ 406: "Not Acceptable",
+ 407: "Proxy Authentication Required",
+ 408: "Request Timeout",
+ 409: "Conflict",
+ 410: "Gone",
+ 411: "Length Required",
+ 412: "Precondition Failed",
+ 413: "Payload Too Large",
+ 414: "URI Too Long",
+ 415: "Unsupported Media Type",
+ 416: "Range Not Satisfiable",
+ 417: "Expectation Failed",
+ 418: "I'm a Teapot",
+ 421: "Misdirected Request",
+ 422: "Unprocessable Entity",
+ 423: "Locked",
+ 424: "Failed Dependency",
+ 425: "Too Early",
+ 426: "Upgrade Required",
+ 428: "Precondition Required",
+ 429: "Too Many Requests",
+ 431: "Request Header Fields Too Large",
+ 451: "Unavailable For Legal Reasons",
+ 500: "Internal Server Error",
+ 501: "Not Implemented",
+ 502: "Bad Gateway",
+ 503: "Service Unavailable",
+ 504: "Gateway Timeout",
+ 505: "HTTP Version Not Supported",
+ 506: "Variant Also Negotiates",
+ 507: "Insufficient Storage",
+ 508: "Loop Detected",
+ 510: "Not Extended",
+ 511: "Network Authentication Required",
+ };
+
+ for (let code in fixture) {
+ it(`should return ${code} ${fixture[code]}`, async () => {
+ const server = serve({
+ port: port++,
+ fetch(req) {
+ return new Response("hey", { status: +code });
+ },
+ });
+
+ const response = await fetch(`http://${server.hostname}:${server.port}`);
+ expect(response.status).toBe(parseInt(code));
+ expect(response.statusText).toBe(fixture[code]);
+ server.stop();
+ });
+ }
+});