| ... | ... | @@ -15,7 +15,7 @@ const proto = @import("protocol.zig"); |
| 15 | 15 | pub const disable_tls = std.options.http_disable_tls; |
| 16 | 16 | |
| 17 | 17 | allocator: Allocator, |
| 18 | | ca_bundle: std.crypto.Certificate.Bundle = .{}, |
| 18 | ca_bundle: if (disable_tls) void else std.crypto.Certificate.Bundle = if (disable_tls) {} else .{}, |
| 19 | 19 | ca_bundle_mutex: std.Thread.Mutex = .{}, |
| 20 | 20 | |
| 21 | 21 | /// When this is `true`, the next time this client performs an HTTPS request, |
| ... | ... | @@ -386,7 +386,7 @@ pub const Response = struct { |
| 386 | 386 | }; |
| 387 | 387 | |
| 388 | 388 | pub fn parse(res: *Response, bytes: []const u8, trailing: bool) ParseError!void { |
| 389 | | var it = mem.tokenizeAny(u8, bytes[0 .. bytes.len - 4], "\r\n"); |
| 389 | var it = mem.tokenizeAny(u8, bytes, "\r\n"); |
| 390 | 390 | |
| 391 | 391 | const first_line = it.next() orelse return error.HttpHeadersInvalid; |
| 392 | 392 | if (first_line.len < 12) |
| ... | ... | @@ -405,6 +405,8 @@ pub const Response = struct { |
| 405 | 405 | res.status = status; |
| 406 | 406 | res.reason = reason; |
| 407 | 407 | |
| 408 | res.headers.clearRetainingCapacity(); |
| 409 | |
| 408 | 410 | while (it.next()) |line| { |
| 409 | 411 | if (line.len == 0) return error.HttpHeadersInvalid; |
| 410 | 412 | switch (line[0]) { |
| ... | ... | @@ -525,6 +527,7 @@ pub const Request = struct { |
| 525 | 527 | |
| 526 | 528 | redirects_left: u32, |
| 527 | 529 | handle_redirects: bool, |
| 530 | handle_continue: bool, |
| 528 | 531 | |
| 529 | 532 | response: Response, |
| 530 | 533 | |
| ... | ... | @@ -758,6 +761,10 @@ pub const Request = struct { |
| 758 | 761 | if (req.response.status == .@"continue") { |
| 759 | 762 | req.response.parser.done = true; // we're done parsing the continue response, reset to prepare for the real response |
| 760 | 763 | req.response.parser.reset(); |
| 764 | |
| 765 | if (req.handle_continue) |
| 766 | continue; |
| 767 | |
| 761 | 768 | break; |
| 762 | 769 | } |
| 763 | 770 | |
| ... | ... | @@ -897,8 +904,6 @@ pub const Request = struct { |
| 897 | 904 | } |
| 898 | 905 | |
| 899 | 906 | if (has_trail) { |
| 900 | | req.response.headers.clearRetainingCapacity(); |
| 901 | | |
| 902 | 907 | // The response headers before the trailers are already guaranteed to be valid, so they will always be parsed again and cannot return an error. |
| 903 | 908 | // This will *only* fail for a malformed trailer. |
| 904 | 909 | req.response.parse(req.response.parser.header_bytes.items, true) catch return error.InvalidTrailers; |
| ... | ... | @@ -999,7 +1004,9 @@ pub fn deinit(client: *Client) void { |
| 999 | 1004 | proxy.headers.deinit(); |
| 1000 | 1005 | } |
| 1001 | 1006 | |
| 1002 | | client.ca_bundle.deinit(client.allocator); |
| 1007 | if (!disable_tls) |
| 1008 | client.ca_bundle.deinit(client.allocator); |
| 1009 | |
| 1003 | 1010 | client.* = undefined; |
| 1004 | 1011 | } |
| 1005 | 1012 | |
| ... | ... | @@ -1315,6 +1322,14 @@ pub const RequestError = ConnectTcpError || ConnectErrorPartial || Request.SendE |
| 1315 | 1322 | pub const RequestOptions = struct { |
| 1316 | 1323 | version: http.Version = .@"HTTP/1.1", |
| 1317 | 1324 | |
| 1325 | /// Automatically ignore 100 Continue responses. This assumes you don't care, and will have sent the body before you |
| 1326 | /// wait for the response. |
| 1327 | /// |
| 1328 | /// If this is not the case AND you know the server will send a 100 Continue, set this to false and wait for a |
| 1329 | /// response before sending the body. If you wait AND the server does not send a 100 Continue before you finish the |
| 1330 | /// request, then the request *will* deadlock. |
| 1331 | handle_continue: bool = true, |
| 1332 | |
| 1318 | 1333 | handle_redirects: bool = true, |
| 1319 | 1334 | max_redirects: u32 = 3, |
| 1320 | 1335 | header_strategy: StorageStrategy = .{ .dynamic = 16 * 1024 }, |
| ... | ... | @@ -1361,6 +1376,8 @@ pub fn open(client: *Client, method: http.Method, uri: Uri, headers: http.Header |
| 1361 | 1376 | const host = uri.host orelse return error.UriMissingHost; |
| 1362 | 1377 | |
| 1363 | 1378 | if (protocol == .tls and @atomicLoad(bool, &client.next_https_rescan_certs, .Acquire)) { |
| 1379 | if (disable_tls) unreachable; |
| 1380 | |
| 1364 | 1381 | client.ca_bundle_mutex.lock(); |
| 1365 | 1382 | defer client.ca_bundle_mutex.unlock(); |
| 1366 | 1383 | |
| ... | ... | @@ -1381,6 +1398,7 @@ pub fn open(client: *Client, method: http.Method, uri: Uri, headers: http.Header |
| 1381 | 1398 | .version = options.version, |
| 1382 | 1399 | .redirects_left = options.max_redirects, |
| 1383 | 1400 | .handle_redirects = options.handle_redirects, |
| 1401 | .handle_continue = options.handle_continue, |
| 1384 | 1402 | .response = .{ |
| 1385 | 1403 | .status = undefined, |
| 1386 | 1404 | .reason = undefined, |