Created
June 21, 2024 20:54
-
-
Save AdriDevelopsThings/0eee88be85c13f799a813780e8b4889a to your computer and use it in GitHub Desktop.
A simple http server that answers all requests with an infinite big file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
pub const std_options = .{ | |
.log_level = .info, | |
}; | |
fn handle_connection(connection: std.net.Server.Connection, filename: []u8) !void { | |
std.log.info("Client {} connected", .{connection.address}); | |
defer { | |
connection.stream.close(); | |
std.log.info("Client {} disconnected", .{connection.address}); | |
} | |
{ | |
var buffer: [255]u8 = undefined; | |
_ = try connection.stream.read(&buffer); | |
} | |
var prng = std.rand.DefaultPrng.init(blk: { | |
var seed: u64 = undefined; | |
try std.posix.getrandom(std.mem.asBytes(&seed)); | |
break :blk seed; | |
}); | |
const random = prng.random(); | |
try connection.stream.writer().print("HTTP/1.1 200 OK\r\nServer: zig\r\nContent-Type: application/octet-stream\r\nContent-Disposition: attachment; filename=\"{s}\"\r\n\r\n", .{filename}); | |
var downloaded: usize = 0; | |
var out_counter: usize = 0; | |
while (true) { | |
var writeBuffer: [255]u8 = undefined; | |
random.bytes(&writeBuffer); | |
const wrote = connection.stream.write(&writeBuffer) catch |err| switch (err) { | |
error.BrokenPipe => break, | |
error.ConnectionResetByPeer => break, | |
else => return err, | |
}; | |
downloaded += wrote; | |
out_counter += wrote; | |
if (out_counter >= 1024 * 1024 * 1024) { | |
std.log.info("Client {} downloaded {d} GiB", .{ connection.address, downloaded / (1024 * 1024 * 1024) }); | |
out_counter = 0; | |
} | |
} | |
} | |
pub fn main() !void { | |
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | |
const allocator = gpa.allocator(); | |
defer { | |
const check = gpa.deinit(); | |
if (check == .leak) @panic("memory leaks"); | |
} | |
const args = try std.process.argsAlloc(allocator); | |
defer std.process.argsFree(allocator, args); | |
if (args.len != 4) { | |
const writer = std.io.getStdErr().writer(); | |
try writer.print("Usage: {s} DOWNLOAD_FILENAME ADDRESS PORT\n", .{args[0]}); | |
std.process.exit(1); | |
unreachable; | |
} | |
const listen_address = try std.net.Address.resolveIp(args[2], try std.fmt.parseInt(u16, args[3], 10)); | |
var server = try listen_address.listen(.{ .reuse_address = true }); | |
defer server.deinit(); | |
std.log.info("Listening on http://{s}:{s}", .{ args[2], args[3] }); | |
while (true) { | |
const connection = try server.accept(); | |
_ = try std.Thread.spawn(.{}, handle_connection, .{ connection, args[1] }); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment