karlseguin / http.zig

An HTTP/1.1 server for zig
MIT License
533 stars 41 forks source link

Response is not sent and memory is not freed with big body #44

Closed ScuroGuardiano closed 4 months ago

ScuroGuardiano commented 5 months ago

Hello there,

when I assign a lot of data to res.body at the end of a handler, the body is not sent, in insomnia I get an error and, what's worse, the memory allocated with res.arena is not freed. However, if I manually call res.write() then everything works perfectly. Here's code with minimal example of this problem:

const std = @import("std");
const httpz = @import("httpz");

fn bigBoi(_: *httpz.Request, res: *httpz.Response) !void {
    // Let's allocate like 100M of memory
    const data = try res.arena.alloc(u8, 100 * 1024 * 1024);
    @memset(data, 'A');
    res.content_type = .TEXT;
    res.body = data;
}

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    var server = try httpz.Server().init(allocator, .{ .port = 1337 });

    var router = server.router();
    router.get("/", bigBoi);

    std.debug.print("Server will listen now on port 1337\n", .{});
    try server.listen();
}

I also tried to use curl curl http://localhost:1337/ -v | hexdump and it just hangs after downloading about 10MB of data. But if I add try res.write() at the end of the handler then it works perfectly.

karlseguin commented 5 months ago

I believe this is fixed. Unfortunately, I haven't found a reliable way to automatically test this yet, as locally, even with a large buffer, it can succeed. There's probably some socket option that would help trigger this more reliably. But, at least with some manual testing, I was initially able to reproduce it, and now I can't (and I'm pretty sure I correct identified the cause of the issue).

Sorry you ran into this.

ScuroGuardiano commented 4 months ago

I can confirm, last commit fixed the issue.

Thank you for quick reaction <3