Make HTTP status text more consistent with other HTTP servers

This commit is contained in:
Jarred Sumner
2022-11-26 18:03:20 -08:00
parent 90388aa7ea
commit 949d715a14
2 changed files with 153 additions and 2 deletions

View File

@@ -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);
}

View File

@@ -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();
});
}
});