#std.http.Client.RequestOptions Decision

1 messages · Page 1 of 1 (latest)

last grotto
#

Why was the decision made in std.http.Client.RequestOptions to use a .server_header_buffer? I feel like that really locks what the programmer can do. Looking at the open method, in std.http.Client, server_header_buffer is used for an arena. Ok that's fine, but then why not just allow the programmer to pass in an allocator of their choice? I am just so confused by this decision.

ashen mirage
#

because it means the http.Client performs no allocations in the hot path, the header buffer is preallocated

last grotto
ashen mirage
#

if the response is bigger than your buffer then you should have provided a bigger buffer, if you allow unbounded allocations then you open yourself up to malicious servers causing you to endlessly allocate

last grotto
#

Like we were given a choice when it comes to reading the body, why not a choice for the headers?

ashen mirage
#

most webservers can't even produce a response head more than 8-64kb

#

you aren't given a choice because you can place a reasonable upper bound on the size of the response head regardless of server

#

you can't place a reasonable upper bound on the size of the payload without knowing the form of the data

last grotto
last grotto
ashen mirage
#

no you don't, allocate 8 or 16kb, use that as your header buffer; if the server sends you more than 16kb of response head then either the server is likely sending you way too much data

#

std.http.Client used to accept an allocator and resize during the middle of reading the response; the behavior was removed because it was unnecessary and generally just slower

last grotto
#

I agree to what you are saying. However, imo, that should be the programmers choice tho

last grotto
ashen mirage
#

I removed the ability to heap-allocate the buffer for headers. The buffer for HTTP headers is now always provided via a static buffer. As a consequence, OutOfMemory is no longer a member of the read() error set, and the API and implementation of Client and Server are simplified. error.HttpHeadersExceededSizeLimit is renamed to error.HttpHeadersOversize.

last grotto
#

I agree with you that anything more than 16kb is way too much, my issue is that this should be on the programmer. Than again, what do I know if Father Andrew says so

#

Kinda related to this, but do you know why we can't send a body via request.send()? I had to copy and paste the method and add this feature myself

ashen mirage
#

because it has to handle redirects

last grotto
#

True, but like sending a body in an http request is pretty important imo

ashen mirage
#

fetch exists to handle the normal use cases, if you want to use the lower-level Request/Response interface then each component does its own job and nothing else

#

fwiw, I dislike the general direction that std.http has gone because it's gotten less and less maintainable over time; but my time to rework it is limited

last grotto
ashen mirage
#

request doesn't exist

last grotto
#

I should say the client.open then

ashen mirage
#

Client.fetch is a tiny bit of code that takes in common options, does the request, and then returns the data back to you
Client.open is the lower level interface where you perform each step of the request yourself, which allows you to handle potential errors at each step

last grotto
# ashen mirage fwiw, I dislike the general direction that std.http has gone because it's gotten...

I am trying to write a wrapper around it for the same reason tbh. My goal is to make it kinda like the python requests library

fn create_profile(allocator: Allocator, id_number: i32, name: []const u8, age: i32) !void {
    var headers = std.BufMap.init(allocator);
    defer headers.deinit();
    try headers.put("Content-Type", "application/json");

    const request_body: []u8 = try std.fmt.allocPrint(allocator, "{{\"id_number\": {d}, \"name\": \"{s}\", \"age\": {d}}}", .{ id_number, name, age });
    defer allocator.free(request_body);

    var r: requests.Response = try requests.post(allocator, "http://127.0.0.1:55555/", &headers, request_body);
    defer r.deinit();

    print("\n{any} ({d})\n\n", .{ r.status_code, @intFromEnum(r.status_code) });

    var response_headers = r.headers.iterator();

    while (response_headers.next()) |header| {
        print("{s}: {s}\n", .{ header.key_ptr.*, header.value_ptr.* });
    }

    print("\n{s}", .{r.body});
}