144 lines
6.1 KiB
Zig
144 lines
6.1 KiB
Zig
const std = @import("std");
|
|
const main = @import("main.zig");
|
|
|
|
threadlocal var read_buffer: [2 * 1024 * 1024]u8 = undefined;
|
|
threadlocal var write_buffer: [2 * 1024 * 1024]u8 = undefined;
|
|
|
|
const log = std.log.scoped(.http);
|
|
|
|
const status = struct {
|
|
pub const ok = "HTTP/1.1 200 OK\r\n";
|
|
pub const created = "HTTP/1.1 201 Created\r\n";
|
|
pub const accepted = "HTTP/1.1 202 Accepted\r\n";
|
|
pub const non_authoritative_information = "HTTP/1.1 203 Non-Authoritative Information\r\n";
|
|
pub const no_content = "HTTP/1.1 204 No Content\r\n";
|
|
pub const reset_content = "HTTP/1.1 205 Reset Content\r\n";
|
|
pub const partial_content = "HTTP/1.1 206 Partial Content\r\n";
|
|
pub const multi_status = "HTTP/1.1 207 Multi-Status\r\n";
|
|
pub const already_reported = "HTTP/1.1 208 Already Reported\r\n";
|
|
|
|
pub const multiple_choices = "HTTP/1.1 300 Multiple Choices\r\n";
|
|
pub const moved_permanently = "HTTP/1.1 301 Moved Permanently\r\n";
|
|
pub const found = "HTTP/1.1 302 Found\r\n";
|
|
pub const see_other = "HTTP/1.1 303 See Other\r\n";
|
|
pub const not_modified = "HTTP/1.1 304 Not Modified\r\n";
|
|
pub const temporary_redirect = "HTTP/1.1 307 Temporary Redirect\r\n";
|
|
pub const permanent_redirect = "HTTP/1.1 308 Permanent Redirect\r\n";
|
|
|
|
pub const bad_request = "HTTP/1.1 400 Bad Request\r\n";
|
|
pub const unauthorized = "HTTP/1.1 401 Unauthorized\r\n";
|
|
pub const payment_required = "HTTP/1.1 402 Payment Required\r\n";
|
|
pub const forbidden = "HTTP/1.1 403 Forbidden\r\n";
|
|
pub const not_found = "HTTP/1.1 404 Not Found\r\n";
|
|
pub const method_not_allowed = "HTTP/1.1 405 Method Not Allowed\r\n";
|
|
pub const not_acceptable = "HTTP/1.1 406 Not Acceptable\r\n";
|
|
pub const proxy_authentication_required = "HTTP/1.1 407 Proxy Authentication Required\r\n";
|
|
pub const request_timeout = "HTTP/1.1 408 Request Timeout\r\n";
|
|
pub const conflict = "HTTP/1.1 409 Conflict\r\n";
|
|
pub const gone = "HTTP/1.1 410 Gone\r\n";
|
|
pub const length_required = "HTTP/1.1 411 Length Required\r\n";
|
|
pub const precondition_failed = "HTTP/1.1 412 Precondition Failed\r\n";
|
|
pub const content_too_large = "HTTP/1.1 413 Content Too Large\r\n";
|
|
pub const uri_too_long = "HTTP/1.1 414 URI Too Long\r\n";
|
|
pub const unsupported_media_type = "HTTP/1.1 415 Unsupported Media Type\r\n";
|
|
pub const range_not_satisfiable = "HTTP/1.1 416 Range Not Satisfiable\r\n";
|
|
pub const expectation_failed = "HTTP/1.1 417 Expectation Failed\r\n";
|
|
pub const im_a_teapot = "HTTP/1.1 418 I'm a teapot\r\n";
|
|
pub const misdirected_request = "HTTP/1.1 421 Misdirected Request\r\n";
|
|
pub const unprocessable_content = "HTTP/1.1 422 Unprocessable Content\r\n";
|
|
pub const locked = "HTTP/1.1 423 Locked\r\n";
|
|
pub const failed_dependency = "HTTP/1.1 424 Failed Dependency\r\n";
|
|
pub const upgrade_required = "HTTP/1.1 426 Upgrade Required\r\n";
|
|
pub const precondition_required = "HTTP/1.1 428 Precondition Required\r\n";
|
|
pub const too_many_requests = "HTTP/1.1 429 Too Many Requests\r\n";
|
|
pub const request_header_fields_too_large = "HTTP/1.1 431 Request Header Fields Too Large\r\n";
|
|
pub const unavailable_for_legal_reasons = "HTTP/1.1 451 Unavailable For Legal Reasons\r\n";
|
|
|
|
pub const internal_server_error = "HTTP/1.1 500 Internal Server Error\r\n";
|
|
pub const not_implemented = "HTTP/1.1 501 Not Implemented\r\n";
|
|
pub const bad_gateway = "HTTP/1.1 502 Bad Gateway\r\n";
|
|
pub const service_unavailable = "HTTP/1.1 503 Service Unavailable\r\n";
|
|
pub const gateway_timeout = "HTTP/1.1 504 Gateway Timeout\r\n";
|
|
pub const http_version_not_supported = "HTTP/1.1 505 HTTP Version Not Supported\r\n";
|
|
pub const variant_also_negotiates = "HTTP/1.1 506 Variant Also Negotiates\r\n";
|
|
pub const insufficient_storage = "HTTP/1.1 507 Insufficient Storage\r\n";
|
|
pub const loop_detected = "HTTP/1.1 508 Loop Detected\r\n";
|
|
pub const not_extended = "HTTP/1.1 510 Not Extended\r\n";
|
|
pub const network_authentication_required = "HTTP/1.1 511 Network Authentication Required\r\n";
|
|
};
|
|
|
|
const ResponseEmptyOptions = struct {
|
|
status_text: []const u8 = status.ok,
|
|
};
|
|
|
|
const ResponseOptions = struct {
|
|
status_text: []const u8 = status.ok,
|
|
media_type: []const u8 = "text/plain; charset=utf-8",
|
|
response_body: []const u8,
|
|
};
|
|
|
|
fn makeResponseEmpty(options: ResponseEmptyOptions) ![]const u8 {
|
|
var fbs = std.io.fixedBufferStream(&write_buffer);
|
|
const writer = fbs.writer();
|
|
|
|
try writer.print("{s}", .{options.status_text});
|
|
try writer.print("\r\n", .{});
|
|
|
|
return fbs.getWritten();
|
|
}
|
|
|
|
fn makeResponse(options: ResponseOptions) ![]const u8 {
|
|
var fbs = std.io.fixedBufferStream(&write_buffer);
|
|
const writer = fbs.writer();
|
|
|
|
try writer.print("{s}", .{options.status_text});
|
|
try writer.print("Content-Type: {s}\r\n", .{options.media_type});
|
|
try writer.print("Content-Length: {d}\r\n", .{options.response_body.len});
|
|
try writer.print("\r\n", .{});
|
|
try writer.print("{s}", .{options.response_body});
|
|
|
|
return fbs.getWritten();
|
|
}
|
|
|
|
pub fn process(conn: std.net.Server.Connection) !void {
|
|
defer conn.stream.close();
|
|
|
|
var arena = std.heap.ArenaAllocator.init(main.allocator);
|
|
defer arena.deinit();
|
|
|
|
const allocator = arena.allocator();
|
|
_ = allocator;
|
|
|
|
var running = true;
|
|
while (running) {
|
|
var header_end: ?usize = null;
|
|
var request_len: usize = 0;
|
|
|
|
const request_head = blk: while (conn.stream.read(read_buffer[request_len..])) |len| {
|
|
if (len == 0) {
|
|
running = false;
|
|
return;
|
|
}
|
|
|
|
header_end = std.mem.indexOfPos(u8, &read_buffer, request_len, "\r\n\r\n");
|
|
request_len += len;
|
|
|
|
if (header_end) |end| {
|
|
break :blk read_buffer[0..end];
|
|
}
|
|
} else |err| {
|
|
return err;
|
|
};
|
|
|
|
const response = try makeResponse(.{
|
|
.response_body = "PONG\n",
|
|
});
|
|
|
|
try conn.stream.writeAll(response);
|
|
|
|
if (request_len > request_head.len + 4) {
|
|
@memmove(&read_buffer, read_buffer[request_head.len + 4 .. request_len]);
|
|
}
|
|
}
|
|
}
|