| author | |
| committer | |
| log | 7b0962938859a955fa8e057ef34f4abd925bb1ca |
| tree | 4e9a27685b5512241f62c8283ddd7f0226a4e63d |
| parent | 533049fdd80a4c7bc3098512b4033a60daea745e |
| signature | Commit is signed but in an unrecognized format. |
2 files changed, 88 insertions(+), 36 deletions(-)
lib/std/http/Client.zig+44-18| ... | ... | @@ -254,44 +254,47 @@ pub const BufferedConnection = struct { |
| 254 | 254 | pub const buffer_size = 0x2000; |
| 255 | 255 | |
| 256 | 256 | conn: Connection, |
| 257 | buf: [buffer_size]u8 = undefined, | |
| 258 | start: u16 = 0, | |
| 259 | end: u16 = 0, | |
| 257 | read_buf: [buffer_size]u8 = undefined, | |
| 258 | read_start: u16 = 0, | |
| 259 | read_end: u16 = 0, | |
| 260 | ||
| 261 | write_buf: [buffer_size]u8 = undefined, | |
| 262 | write_end: u16 = 0, | |
| 260 | 263 | |
| 261 | 264 | pub fn fill(bconn: *BufferedConnection) ReadError!void { |
| 262 | if (bconn.end != bconn.start) return; | |
| 265 | if (bconn.read_end != bconn.read_start) return; | |
| 263 | 266 | |
| 264 | const nread = try bconn.conn.read(bconn.buf[0..]); | |
| 267 | const nread = try bconn.conn.read(bconn.read_buf[0..]); | |
| 265 | 268 | if (nread == 0) return error.EndOfStream; |
| 266 | bconn.start = 0; | |
| 267 | bconn.end = @intCast(u16, nread); | |
| 269 | bconn.read_start = 0; | |
| 270 | bconn.read_end = @intCast(u16, nread); | |
| 268 | 271 | } |
| 269 | 272 | |
| 270 | 273 | pub fn peek(bconn: *BufferedConnection) []const u8 { |
| 271 | return bconn.buf[bconn.start..bconn.end]; | |
| 274 | return bconn.read_buf[bconn.read_start..bconn.read_end]; | |
| 272 | 275 | } |
| 273 | 276 | |
| 274 | 277 | pub fn clear(bconn: *BufferedConnection, num: u16) void { |
| 275 | bconn.start += num; | |
| 278 | bconn.read_start += num; | |
| 276 | 279 | } |
| 277 | 280 | |
| 278 | 281 | pub fn readAtLeast(bconn: *BufferedConnection, buffer: []u8, len: usize) ReadError!usize { |
| 279 | 282 | var out_index: u16 = 0; |
| 280 | 283 | while (out_index < len) { |
| 281 | const available = bconn.end - bconn.start; | |
| 284 | const available = bconn.read_end - bconn.read_start; | |
| 282 | 285 | const left = buffer.len - out_index; |
| 283 | 286 | |
| 284 | 287 | if (available > 0) { |
| 285 | 288 | const can_read = @intCast(u16, @min(available, left)); |
| 286 | 289 | |
| 287 | @memcpy(buffer[out_index..][0..can_read], bconn.buf[bconn.start..][0..can_read]); | |
| 290 | @memcpy(buffer[out_index..][0..can_read], bconn.read_buf[bconn.read_start..][0..can_read]); | |
| 288 | 291 | out_index += can_read; |
| 289 | bconn.start += can_read; | |
| 292 | bconn.read_start += can_read; | |
| 290 | 293 | |
| 291 | 294 | continue; |
| 292 | 295 | } |
| 293 | 296 | |
| 294 | if (left > bconn.buf.len) { | |
| 297 | if (left > bconn.read_buf.len) { | |
| 295 | 298 | // skip the buffer if the output is large enough |
| 296 | 299 | return bconn.conn.read(buffer[out_index..]); |
| 297 | 300 | } |
| ... | ... | @@ -314,11 +317,33 @@ pub const BufferedConnection = struct { |
| 314 | 317 | } |
| 315 | 318 | |
| 316 | 319 | pub fn writeAll(bconn: *BufferedConnection, buffer: []const u8) WriteError!void { |
| 317 | return bconn.conn.writeAll(buffer); | |
| 320 | if (bconn.write_buf.len - bconn.write_end <= buffer.len) { | |
| 321 | @memcpy(bconn.write_buf[bconn.write_end..], buffer); | |
| 322 | bconn.write_end += @intCast(u16, buffer.len); | |
| 323 | } else { | |
| 324 | try bconn.conn.writeAll(bconn.write_buf[0..bconn.write_end]); | |
| 325 | bconn.write_end = 0; | |
| 326 | ||
| 327 | try bconn.conn.writeAll(buffer); | |
| 328 | } | |
| 318 | 329 | } |
| 319 | 330 | |
| 320 | 331 | pub fn write(bconn: *BufferedConnection, buffer: []const u8) WriteError!usize { |
| 321 | return bconn.conn.write(buffer); | |
| 332 | if (bconn.write_buf.len - bconn.write_end <= buffer.len) { | |
| 333 | @memcpy(bconn.write_buf[bconn.write_end..], buffer); | |
| 334 | bconn.write_end += @intCast(u16, buffer.len); | |
| 335 | ||
| 336 | return buffer.len; | |
| 337 | } else { | |
| 338 | try bconn.conn.writeAll(bconn.write_buf[0..bconn.write_end]); | |
| 339 | bconn.write_end = 0; | |
| 340 | ||
| 341 | return try bconn.conn.write(buffer); | |
| 342 | } | |
| 343 | } | |
| 344 | ||
| 345 | pub fn flush(bconn: *BufferedConnection) WriteError!void { | |
| 346 | return bconn.conn.writeAll(bconn.write_buf[0..bconn.write_end]); | |
| 322 | 347 | } |
| 323 | 348 | |
| 324 | 349 | pub const WriteError = Connection.WriteError; |
| ... | ... | @@ -567,8 +592,7 @@ pub const Request = struct { |
| 567 | 592 | |
| 568 | 593 | /// Send the request to the server. |
| 569 | 594 | pub fn start(req: *Request) StartError!void { |
| 570 | var buffered = std.io.bufferedWriter(req.connection.data.buffered.writer()); | |
| 571 | const w = buffered.writer(); | |
| 595 | const w = req.connection.data.buffered.writer(); | |
| 572 | 596 | |
| 573 | 597 | try w.writeAll(@tagName(req.method)); |
| 574 | 598 | try w.writeByte(' '); |
| ... | ... | @@ -642,7 +666,7 @@ pub const Request = struct { |
| 642 | 666 | |
| 643 | 667 | try w.writeAll("\r\n"); |
| 644 | 668 | |
| 645 | try buffered.flush(); | |
| 669 | try req.connection.data.buffered.flush(); | |
| 646 | 670 | } |
| 647 | 671 | |
| 648 | 672 | pub const TransferReadError = BufferedConnection.ReadError || proto.HeadersParser.ReadError; |
| ... | ... | @@ -868,6 +892,8 @@ pub const Request = struct { |
| 868 | 892 | .content_length => |len| if (len != 0) return error.MessageNotCompleted, |
| 869 | 893 | .none => {}, |
| 870 | 894 | } |
| 895 | ||
| 896 | try req.connection.data.buffered.flush(); | |
| 871 | 897 | } |
| 872 | 898 | }; |
| 873 | 899 |
lib/std/http/Server.zig+44-18| ... | ... | @@ -98,44 +98,47 @@ pub const BufferedConnection = struct { |
| 98 | 98 | pub const buffer_size = 0x2000; |
| 99 | 99 | |
| 100 | 100 | conn: Connection, |
| 101 | buf: [buffer_size]u8 = undefined, | |
| 102 | start: u16 = 0, | |
| 103 | end: u16 = 0, | |
| 101 | read_buf: [buffer_size]u8 = undefined, | |
| 102 | read_start: u16 = 0, | |
| 103 | read_end: u16 = 0, | |
| 104 | ||
| 105 | write_buf: [buffer_size]u8 = undefined, | |
| 106 | write_end: u16 = 0, | |
| 104 | 107 | |
| 105 | 108 | pub fn fill(bconn: *BufferedConnection) ReadError!void { |
| 106 | if (bconn.end != bconn.start) return; | |
| 109 | if (bconn.read_end != bconn.read_start) return; | |
| 107 | 110 | |
| 108 | const nread = try bconn.conn.read(bconn.buf[0..]); | |
| 111 | const nread = try bconn.conn.read(bconn.read_buf[0..]); | |
| 109 | 112 | if (nread == 0) return error.EndOfStream; |
| 110 | bconn.start = 0; | |
| 111 | bconn.end = @intCast(u16, nread); | |
| 113 | bconn.read_start = 0; | |
| 114 | bconn.read_end = @intCast(u16, nread); | |
| 112 | 115 | } |
| 113 | 116 | |
| 114 | 117 | pub fn peek(bconn: *BufferedConnection) []const u8 { |
| 115 | return bconn.buf[bconn.start..bconn.end]; | |
| 118 | return bconn.read_buf[bconn.read_start..bconn.read_end]; | |
| 116 | 119 | } |
| 117 | 120 | |
| 118 | 121 | pub fn clear(bconn: *BufferedConnection, num: u16) void { |
| 119 | bconn.start += num; | |
| 122 | bconn.read_start += num; | |
| 120 | 123 | } |
| 121 | 124 | |
| 122 | 125 | pub fn readAtLeast(bconn: *BufferedConnection, buffer: []u8, len: usize) ReadError!usize { |
| 123 | 126 | var out_index: u16 = 0; |
| 124 | 127 | while (out_index < len) { |
| 125 | const available = bconn.end - bconn.start; | |
| 128 | const available = bconn.read_end - bconn.read_start; | |
| 126 | 129 | const left = buffer.len - out_index; |
| 127 | 130 | |
| 128 | 131 | if (available > 0) { |
| 129 | 132 | const can_read = @intCast(u16, @min(available, left)); |
| 130 | 133 | |
| 131 | @memcpy(buffer[out_index..][0..can_read], bconn.buf[bconn.start..][0..can_read]); | |
| 134 | @memcpy(buffer[out_index..][0..can_read], bconn.read_buf[bconn.read_start..][0..can_read]); | |
| 132 | 135 | out_index += can_read; |
| 133 | bconn.start += can_read; | |
| 136 | bconn.read_start += can_read; | |
| 134 | 137 | |
| 135 | 138 | continue; |
| 136 | 139 | } |
| 137 | 140 | |
| 138 | if (left > bconn.buf.len) { | |
| 141 | if (left > bconn.read_buf.len) { | |
| 139 | 142 | // skip the buffer if the output is large enough |
| 140 | 143 | return bconn.conn.read(buffer[out_index..]); |
| 141 | 144 | } |
| ... | ... | @@ -158,11 +161,33 @@ pub const BufferedConnection = struct { |
| 158 | 161 | } |
| 159 | 162 | |
| 160 | 163 | pub fn writeAll(bconn: *BufferedConnection, buffer: []const u8) WriteError!void { |
| 161 | return bconn.conn.writeAll(buffer); | |
| 164 | if (bconn.write_buf.len - bconn.write_end <= buffer.len) { | |
| 165 | @memcpy(bconn.write_buf[bconn.write_end..], buffer); | |
| 166 | bconn.write_end += @intCast(u16, buffer.len); | |
| 167 | } else { | |
| 168 | try bconn.conn.writeAll(bconn.write_buf[0..bconn.write_end]); | |
| 169 | bconn.write_end = 0; | |
| 170 | ||
| 171 | try bconn.conn.writeAll(buffer); | |
| 172 | } | |
| 162 | 173 | } |
| 163 | 174 | |
| 164 | 175 | pub fn write(bconn: *BufferedConnection, buffer: []const u8) WriteError!usize { |
| 165 | return bconn.conn.write(buffer); | |
| 176 | if (bconn.write_buf.len - bconn.write_end <= buffer.len) { | |
| 177 | @memcpy(bconn.write_buf[bconn.write_end..], buffer); | |
| 178 | bconn.write_end += @intCast(u16, buffer.len); | |
| 179 | ||
| 180 | return buffer.len; | |
| 181 | } else { | |
| 182 | try bconn.conn.writeAll(bconn.write_buf[0..bconn.write_end]); | |
| 183 | bconn.write_end = 0; | |
| 184 | ||
| 185 | return try bconn.conn.write(buffer); | |
| 186 | } | |
| 187 | } | |
| 188 | ||
| 189 | pub fn flush(bconn: *BufferedConnection) WriteError!void { | |
| 190 | return bconn.conn.writeAll(bconn.write_buf[0..bconn.write_end]); | |
| 166 | 191 | } |
| 167 | 192 | |
| 168 | 193 | pub const WriteError = Connection.WriteError; |
| ... | ... | @@ -426,8 +451,7 @@ pub const Response = struct { |
| 426 | 451 | .first, .start, .responded, .finished => unreachable, |
| 427 | 452 | } |
| 428 | 453 | |
| 429 | var buffered = std.io.bufferedWriter(res.connection.writer()); | |
| 430 | const w = buffered.writer(); | |
| 454 | const w = res.connection.writer(); | |
| 431 | 455 | |
| 432 | 456 | try w.writeAll(@tagName(res.version)); |
| 433 | 457 | try w.writeByte(' '); |
| ... | ... | @@ -485,7 +509,7 @@ pub const Response = struct { |
| 485 | 509 | |
| 486 | 510 | try w.writeAll("\r\n"); |
| 487 | 511 | |
| 488 | try buffered.flush(); | |
| 512 | try res.connection.flush(); | |
| 489 | 513 | } |
| 490 | 514 | |
| 491 | 515 | pub const TransferReadError = BufferedConnection.ReadError || proto.HeadersParser.ReadError; |
| ... | ... | @@ -669,6 +693,8 @@ pub const Response = struct { |
| 669 | 693 | .content_length => |len| if (len != 0) return error.MessageNotCompleted, |
| 670 | 694 | .none => {}, |
| 671 | 695 | } |
| 696 | ||
| 697 | try res.connection.flush(); | |
| 672 | 698 | } |
| 673 | 699 | }; |
| 674 | 700 |