| ... | @@ -16,6 +16,7 @@ pub const Request = struct { | ... | @@ -16,6 +16,7 @@ pub const Request = struct { |
| 16 | headers: std.ArrayListUnmanaged(u8) = .{}, | 16 | headers: std.ArrayListUnmanaged(u8) = .{}, |
| 17 | tls_client: std.crypto.tls.Client, | 17 | tls_client: std.crypto.tls.Client, |
| 18 | protocol: Protocol, | 18 | protocol: Protocol, |
| | 19 | response_headers: http.Headers = .{}, |
| 19 | | 20 | |
| 20 | pub const Protocol = enum { http, https }; | 21 | pub const Protocol = enum { http, https }; |
| 21 | | 22 | |
| ... | @@ -51,18 +52,53 @@ pub const Request = struct { | ... | @@ -51,18 +52,53 @@ pub const Request = struct { |
| 51 | } | 52 | } |
| 52 | } | 53 | } |
| 53 | | 54 | |
| | 55 | pub fn readAll(req: *Request, buffer: []u8) !usize { |
| | 56 | return readAtLeast(req, buffer, buffer.len); |
| | 57 | } |
| | 58 | |
| 54 | pub fn read(req: *Request, buffer: []u8) !usize { | 59 | pub fn read(req: *Request, buffer: []u8) !usize { |
| | 60 | return readAtLeast(req, buffer, 1); |
| | 61 | } |
| | 62 | |
| | 63 | pub fn readAtLeast(req: *Request, buffer: []u8, len: usize) !usize { |
| | 64 | assert(len <= buffer.len); |
| | 65 | var index: usize = 0; |
| | 66 | while (index < len) { |
| | 67 | const headers_finished = req.response_headers.state == .finished; |
| | 68 | const amt = try readAdvanced(req, buffer[index..]); |
| | 69 | if (amt == 0 and headers_finished) break; |
| | 70 | index += amt; |
| | 71 | } |
| | 72 | return index; |
| | 73 | } |
| | 74 | |
| | 75 | /// This one can return 0 without meaning EOF. |
| | 76 | /// TODO change to readvAdvanced |
| | 77 | pub fn readAdvanced(req: *Request, buffer: []u8) !usize { |
| | 78 | if (req.response_headers.state == .finished) return readRaw(req, buffer); |
| | 79 | |
| | 80 | const amt = try readRaw(req, buffer); |
| | 81 | const data = buffer[0..amt]; |
| | 82 | const i = req.response_headers.feed(data); |
| | 83 | if (req.response_headers.state == .invalid) return error.InvalidHttpHeaders; |
| | 84 | if (i < data.len) { |
| | 85 | const rest = data[i..]; |
| | 86 | std.mem.copy(u8, buffer, rest); |
| | 87 | return rest.len; |
| | 88 | } |
| | 89 | return 0; |
| | 90 | } |
| | 91 | |
| | 92 | /// Only abstracts over http/https. |
| | 93 | fn readRaw(req: *Request, buffer: []u8) !usize { |
| 55 | switch (req.protocol) { | 94 | switch (req.protocol) { |
| 56 | .http => return req.stream.read(buffer), | 95 | .http => return req.stream.read(buffer), |
| 57 | .https => return req.tls_client.read(req.stream, buffer), | 96 | .https => return req.tls_client.read(req.stream, buffer), |
| 58 | } | 97 | } |
| 59 | } | 98 | } |
| 60 | | 99 | |
| 61 | pub fn readAll(req: *Request, buffer: []u8) !usize { | 100 | /// Only abstracts over http/https. |
| 62 | return readAtLeast(req, buffer, buffer.len); | 101 | fn readAtLeastRaw(req: *Request, buffer: []u8, len: usize) !usize { |
| 63 | } | | |
| 64 | | | |
| 65 | pub fn readAtLeast(req: *Request, buffer: []u8, len: usize) !usize { | | |
| 66 | switch (req.protocol) { | 102 | switch (req.protocol) { |
| 67 | .http => return req.stream.readAtLeast(buffer, len), | 103 | .http => return req.stream.readAtLeast(buffer, len), |
| 68 | .https => return req.tls_client.readAtLeast(req.stream, buffer, len), | 104 | .https => return req.tls_client.readAtLeast(req.stream, buffer, len), |