| ... | ... | @@ -527,7 +527,7 @@ pub const Request = struct { |
| 527 | 527 | pub const StartError = BufferedConnection.WriteError || error{ InvalidContentLength, UnsupportedTransferEncoding }; |
| 528 | 528 | |
| 529 | 529 | /// Send the request to the server. |
| 530 | | pub fn start(req: *Request, uri: Uri) StartError!void { |
| 530 | pub fn start(req: *Request) StartError!void { |
| 531 | 531 | var buffered = std.io.bufferedWriter(req.connection.data.buffered.writer()); |
| 532 | 532 | const w = buffered.writer(); |
| 533 | 533 | |
| ... | ... | @@ -535,14 +535,14 @@ pub const Request = struct { |
| 535 | 535 | try w.writeByte(' '); |
| 536 | 536 | |
| 537 | 537 | if (req.method == .CONNECT) { |
| 538 | | try w.writeAll(uri.host.?); |
| 538 | try w.writeAll(req.uri.host.?); |
| 539 | 539 | try w.writeByte(':'); |
| 540 | | try w.print("{}", .{uri.port.?}); |
| 540 | try w.print("{}", .{req.uri.port.?}); |
| 541 | 541 | } else if (req.connection.data.proxied) { |
| 542 | 542 | // proxied connections require the full uri |
| 543 | | try w.print("{+/}", .{uri}); |
| 543 | try w.print("{+/}", .{req.uri}); |
| 544 | 544 | } else { |
| 545 | | try w.print("{/}", .{uri}); |
| 545 | try w.print("{/}", .{req.uri}); |
| 546 | 546 | } |
| 547 | 547 | |
| 548 | 548 | try w.writeByte(' '); |
| ... | ... | @@ -551,7 +551,7 @@ pub const Request = struct { |
| 551 | 551 | |
| 552 | 552 | if (!req.headers.contains("host")) { |
| 553 | 553 | try w.writeAll("Host: "); |
| 554 | | try w.writeAll(uri.host.?); |
| 554 | try w.writeAll(req.uri.host.?); |
| 555 | 555 | try w.writeAll("\r\n"); |
| 556 | 556 | } |
| 557 | 557 | |
| ... | ... | @@ -704,8 +704,7 @@ pub const Request = struct { |
| 704 | 704 | req.arena.deinit(); |
| 705 | 705 | req.arena = new_arena; |
| 706 | 706 | |
| 707 | | const new_req = try req.client.request(resolved_url, req.headers, .{ |
| 708 | | .method = req.method, |
| 707 | const new_req = try req.client.request(req.method, resolved_url, req.headers, .{ |
| 709 | 708 | .version = req.version, |
| 710 | 709 | .max_redirects = req.redirects_left - 1, |
| 711 | 710 | .header_strategy = if (req.response.parser.header_bytes_owned) .{ |
| ... | ... | @@ -738,7 +737,7 @@ pub const Request = struct { |
| 738 | 737 | } |
| 739 | 738 | } |
| 740 | 739 | |
| 741 | | pub const ReadError = TransferReadError || proto.HeadersParser.CheckCompleteHeadError || error{DecompressionFailure}; |
| 740 | pub const ReadError = TransferReadError || proto.HeadersParser.CheckCompleteHeadError || error{ DecompressionFailure, InvalidTrailers }; |
| 742 | 741 | |
| 743 | 742 | pub const Reader = std.io.Reader(*Request, ReadError, read); |
| 744 | 743 | |
| ... | ... | @@ -756,12 +755,22 @@ pub const Request = struct { |
| 756 | 755 | }; |
| 757 | 756 | |
| 758 | 757 | if (out_index == 0) { |
| 758 | const has_trail = !req.response.parser.state.isContent(); |
| 759 | |
| 759 | 760 | while (!req.response.parser.state.isContent()) { // read trailing headers |
| 760 | 761 | try req.connection.data.buffered.fill(); |
| 761 | 762 | |
| 762 | 763 | const nchecked = try req.response.parser.checkCompleteHead(req.client.allocator, req.connection.data.buffered.peek()); |
| 763 | 764 | req.connection.data.buffered.clear(@intCast(u16, nchecked)); |
| 764 | 765 | } |
| 766 | |
| 767 | if (has_trail) { |
| 768 | req.response.headers = http.Headers{ .allocator = req.client.allocator, .owned = false }; |
| 769 | |
| 770 | // The response headers before the trailers are already guaranteed to be valid, so they will always be parsed again and cannot return an error. |
| 771 | // This will *only* fail for a malformed trailer. |
| 772 | req.response.parse(req.response.parser.header_bytes.items) catch return error.InvalidTrailers; |
| 773 | } |
| 765 | 774 | } |
| 766 | 775 | |
| 767 | 776 | return out_index; |
| ... | ... | @@ -943,7 +952,6 @@ pub const RequestError = ConnectUnproxiedError || ConnectErrorPartial || Request |
| 943 | 952 | }; |
| 944 | 953 | |
| 945 | 954 | pub const Options = struct { |
| 946 | | method: http.Method = .GET, |
| 947 | 955 | version: http.Version = .@"HTTP/1.1", |
| 948 | 956 | |
| 949 | 957 | handle_redirects: bool = true, |
| ... | ... | @@ -976,7 +984,7 @@ pub const protocol_map = std.ComptimeStringMap(Connection.Protocol, .{ |
| 976 | 984 | |
| 977 | 985 | /// Form and send a http request to a server. |
| 978 | 986 | /// This function is threadsafe. |
| 979 | | pub fn request(client: *Client, uri: Uri, headers: http.Headers, options: Options) RequestError!Request { |
| 987 | pub fn request(client: *Client, method: http.Method, uri: Uri, headers: http.Headers, options: Options) RequestError!Request { |
| 980 | 988 | const protocol = protocol_map.get(uri.scheme) orelse return error.UnsupportedUrlScheme; |
| 981 | 989 | |
| 982 | 990 | const port: u16 = uri.port orelse switch (protocol) { |
| ... | ... | @@ -1003,7 +1011,7 @@ pub fn request(client: *Client, uri: Uri, headers: http.Headers, options: Option |
| 1003 | 1011 | .client = client, |
| 1004 | 1012 | .connection = conn, |
| 1005 | 1013 | .headers = headers, |
| 1006 | | .method = options.method, |
| 1014 | .method = method, |
| 1007 | 1015 | .version = options.version, |
| 1008 | 1016 | .redirects_left = options.max_redirects, |
| 1009 | 1017 | .handle_redirects = options.handle_redirects, |