| author | |
| committer | |
| log | 544ed34d99f59a1b487341eaaa9610be44629924 |
| tree | 4e14e3404ac1d3eb0ea12fcbd6b7b040a0c9cfb3 |
| parent | d4cf8ea0b7621f7757203ecdbaa760e99cbc455c |
| signature |
Response.do was renamed to Response.start to mimic the
naming scheme in http.Client3 files changed, 31 insertions(+), 17 deletions(-)
lib/std/http/Client.zig+1-1| ... | @@ -605,7 +605,7 @@ pub const Request = struct { | ... | @@ -605,7 +605,7 @@ pub const Request = struct { |
| 605 | raw_uri: bool = false, | 605 | raw_uri: bool = false, |
| 606 | }; | 606 | }; |
| 607 | 607 | ||
| 608 | /// Send the HTTP request to the server. | 608 | /// Send the HTTP request headers to the server. |
| 609 | pub fn start(req: *Request, options: StartOptions) StartError!void { | 609 | pub fn start(req: *Request, options: StartOptions) StartError!void { |
| 610 | if (!req.method.requestHasBody() and req.transfer_encoding != .none) return error.UnsupportedTransferEncoding; | 610 | if (!req.method.requestHasBody() and req.transfer_encoding != .none) return error.UnsupportedTransferEncoding; |
| 611 | 611 |
lib/std/http/Server.zig+18-4| ... | @@ -14,7 +14,7 @@ allocator: Allocator, | ... | @@ -14,7 +14,7 @@ allocator: Allocator, |
| 14 | 14 | ||
| 15 | socket: net.StreamServer, | 15 | socket: net.StreamServer, |
| 16 | 16 | ||
| 17 | /// An interface to either a plain or TLS connection. | 17 | /// An interface to a plain connection. |
| 18 | pub const Connection = struct { | 18 | pub const Connection = struct { |
| 19 | pub const buffer_size = std.crypto.tls.max_ciphertext_record_len; | 19 | pub const buffer_size = std.crypto.tls.max_ciphertext_record_len; |
| 20 | pub const Protocol = enum { plain }; | 20 | pub const Protocol = enum { plain }; |
| ... | @@ -273,8 +273,13 @@ pub const Request = struct { | ... | @@ -273,8 +273,13 @@ pub const Request = struct { |
| 273 | target: []const u8, | 273 | target: []const u8, |
| 274 | version: http.Version, | 274 | version: http.Version, |
| 275 | 275 | ||
| 276 | /// The length of the request body, if known. | ||
| 276 | content_length: ?u64 = null, | 277 | content_length: ?u64 = null, |
| 278 | |||
| 279 | /// The transfer encoding of the request body, or .none if not present. | ||
| 277 | transfer_encoding: http.TransferEncoding = .none, | 280 | transfer_encoding: http.TransferEncoding = .none, |
| 281 | |||
| 282 | /// The compression of the request body, or .identity (no compression) if not present. | ||
| 278 | transfer_compression: http.ContentEncoding = .identity, | 283 | transfer_compression: http.ContentEncoding = .identity, |
| 279 | 284 | ||
| 280 | headers: http.Headers, | 285 | headers: http.Headers, |
| ... | @@ -311,6 +316,7 @@ pub const Response = struct { | ... | @@ -311,6 +316,7 @@ pub const Response = struct { |
| 311 | finished, | 316 | finished, |
| 312 | }; | 317 | }; |
| 313 | 318 | ||
| 319 | /// Free all resources associated with this response. | ||
| 314 | pub fn deinit(res: *Response) void { | 320 | pub fn deinit(res: *Response) void { |
| 315 | res.connection.close(); | 321 | res.connection.close(); |
| 316 | 322 | ||
| ... | @@ -386,10 +392,10 @@ pub const Response = struct { | ... | @@ -386,10 +392,10 @@ pub const Response = struct { |
| 386 | } | 392 | } |
| 387 | } | 393 | } |
| 388 | 394 | ||
| 389 | pub const DoError = Connection.WriteError || error{ UnsupportedTransferEncoding, InvalidContentLength }; | 395 | pub const StartError = Connection.WriteError || error{ UnsupportedTransferEncoding, InvalidContentLength }; |
| 390 | 396 | ||
| 391 | /// Send the response headers. | 397 | /// Send the HTTP response headers to the client. |
| 392 | pub fn do(res: *Response) DoError!void { | 398 | pub fn start(res: *Response) StartError!void { |
| 393 | switch (res.state) { | 399 | switch (res.state) { |
| 394 | .waited => res.state = .responded, | 400 | .waited => res.state = .responded, |
| 395 | .first, .start, .responded, .finished => unreachable, | 401 | .first, .start, .responded, .finished => unreachable, |
| ... | @@ -548,6 +554,7 @@ pub const Response = struct { | ... | @@ -548,6 +554,7 @@ pub const Response = struct { |
| 548 | return .{ .context = res }; | 554 | return .{ .context = res }; |
| 549 | } | 555 | } |
| 550 | 556 | ||
| 557 | /// Reads data from the response body. Must be called after `wait`. | ||
| 551 | pub fn read(res: *Response, buffer: []u8) ReadError!usize { | 558 | pub fn read(res: *Response, buffer: []u8) ReadError!usize { |
| 552 | switch (res.state) { | 559 | switch (res.state) { |
| 553 | .waited, .responded, .finished => {}, | 560 | .waited, .responded, .finished => {}, |
| ... | @@ -583,6 +590,7 @@ pub const Response = struct { | ... | @@ -583,6 +590,7 @@ pub const Response = struct { |
| 583 | return out_index; | 590 | return out_index; |
| 584 | } | 591 | } |
| 585 | 592 | ||
| 593 | /// Reads data from the response body. Must be called after `wait`. | ||
| 586 | pub fn readAll(res: *Response, buffer: []u8) !usize { | 594 | pub fn readAll(res: *Response, buffer: []u8) !usize { |
| 587 | var index: usize = 0; | 595 | var index: usize = 0; |
| 588 | while (index < buffer.len) { | 596 | while (index < buffer.len) { |
| ... | @@ -602,6 +610,7 @@ pub const Response = struct { | ... | @@ -602,6 +610,7 @@ pub const Response = struct { |
| 602 | } | 610 | } |
| 603 | 611 | ||
| 604 | /// Write `bytes` to the server. The `transfer_encoding` request header determines how data will be sent. | 612 | /// Write `bytes` to the server. The `transfer_encoding` request header determines how data will be sent. |
| 613 | /// Must be called after `start` and before `finish`. | ||
| 605 | pub fn write(res: *Response, bytes: []const u8) WriteError!usize { | 614 | pub fn write(res: *Response, bytes: []const u8) WriteError!usize { |
| 606 | switch (res.state) { | 615 | switch (res.state) { |
| 607 | .responded => {}, | 616 | .responded => {}, |
| ... | @@ -627,6 +636,8 @@ pub const Response = struct { | ... | @@ -627,6 +636,8 @@ pub const Response = struct { |
| 627 | } | 636 | } |
| 628 | } | 637 | } |
| 629 | 638 | ||
| 639 | /// Write `bytes` to the server. The `transfer_encoding` request header determines how data will be sent. | ||
| 640 | /// Must be called after `start` and before `finish`. | ||
| 630 | pub fn writeAll(req: *Response, bytes: []const u8) WriteError!void { | 641 | pub fn writeAll(req: *Response, bytes: []const u8) WriteError!void { |
| 631 | var index: usize = 0; | 642 | var index: usize = 0; |
| 632 | while (index < bytes.len) { | 643 | while (index < bytes.len) { |
| ... | @@ -637,6 +648,7 @@ pub const Response = struct { | ... | @@ -637,6 +648,7 @@ pub const Response = struct { |
| 637 | pub const FinishError = WriteError || error{MessageNotCompleted}; | 648 | pub const FinishError = WriteError || error{MessageNotCompleted}; |
| 638 | 649 | ||
| 639 | /// Finish the body of a request. This notifies the server that you have no more data to send. | 650 | /// Finish the body of a request. This notifies the server that you have no more data to send. |
| 651 | /// Must be called after `start`. | ||
| 640 | pub fn finish(res: *Response) FinishError!void { | 652 | pub fn finish(res: *Response) FinishError!void { |
| 641 | switch (res.state) { | 653 | switch (res.state) { |
| 642 | .responded => res.state = .finished, | 654 | .responded => res.state = .finished, |
| ... | @@ -651,6 +663,7 @@ pub const Response = struct { | ... | @@ -651,6 +663,7 @@ pub const Response = struct { |
| 651 | } | 663 | } |
| 652 | }; | 664 | }; |
| 653 | 665 | ||
| 666 | /// Create a new HTTP server. | ||
| 654 | pub fn init(allocator: Allocator, options: net.StreamServer.Options) Server { | 667 | pub fn init(allocator: Allocator, options: net.StreamServer.Options) Server { |
| 655 | return .{ | 668 | return .{ |
| 656 | .allocator = allocator, | 669 | .allocator = allocator, |
| ... | @@ -658,6 +671,7 @@ pub fn init(allocator: Allocator, options: net.StreamServer.Options) Server { | ... | @@ -658,6 +671,7 @@ pub fn init(allocator: Allocator, options: net.StreamServer.Options) Server { |
| 658 | }; | 671 | }; |
| 659 | } | 672 | } |
| 660 | 673 | ||
| 674 | /// Free all resources associated with this server. | ||
| 661 | pub fn deinit(server: *Server) void { | 675 | pub fn deinit(server: *Server) void { |
| 662 | server.socket.deinit(); | 676 | server.socket.deinit(); |
| 663 | } | 677 | } |
test/standalone/http.zig+12-12| ... | @@ -29,11 +29,11 @@ fn handleRequest(res: *Server.Response) !void { | ... | @@ -29,11 +29,11 @@ fn handleRequest(res: *Server.Response) !void { |
| 29 | if (res.request.headers.contains("expect")) { | 29 | if (res.request.headers.contains("expect")) { |
| 30 | if (mem.eql(u8, res.request.headers.getFirstValue("expect").?, "100-continue")) { | 30 | if (mem.eql(u8, res.request.headers.getFirstValue("expect").?, "100-continue")) { |
| 31 | res.status = .@"continue"; | 31 | res.status = .@"continue"; |
| 32 | try res.do(); | 32 | try res.start(); |
| 33 | res.status = .ok; | 33 | res.status = .ok; |
| 34 | } else { | 34 | } else { |
| 35 | res.status = .expectation_failed; | 35 | res.status = .expectation_failed; |
| 36 | try res.do(); | 36 | try res.start(); |
| 37 | return; | 37 | return; |
| 38 | } | 38 | } |
| 39 | } | 39 | } |
| ... | @@ -54,7 +54,7 @@ fn handleRequest(res: *Server.Response) !void { | ... | @@ -54,7 +54,7 @@ fn handleRequest(res: *Server.Response) !void { |
| 54 | 54 | ||
| 55 | try res.headers.append("content-type", "text/plain"); | 55 | try res.headers.append("content-type", "text/plain"); |
| 56 | 56 | ||
| 57 | try res.do(); | 57 | try res.start(); |
| 58 | if (res.request.method != .HEAD) { | 58 | if (res.request.method != .HEAD) { |
| 59 | try res.writeAll("Hello, "); | 59 | try res.writeAll("Hello, "); |
| 60 | try res.writeAll("World!\n"); | 60 | try res.writeAll("World!\n"); |
| ... | @@ -65,7 +65,7 @@ fn handleRequest(res: *Server.Response) !void { | ... | @@ -65,7 +65,7 @@ fn handleRequest(res: *Server.Response) !void { |
| 65 | } else if (mem.startsWith(u8, res.request.target, "/large")) { | 65 | } else if (mem.startsWith(u8, res.request.target, "/large")) { |
| 66 | res.transfer_encoding = .{ .content_length = 14 * 1024 + 14 * 10 }; | 66 | res.transfer_encoding = .{ .content_length = 14 * 1024 + 14 * 10 }; |
| 67 | 67 | ||
| 68 | try res.do(); | 68 | try res.start(); |
| 69 | 69 | ||
| 70 | var i: u32 = 0; | 70 | var i: u32 = 0; |
| 71 | while (i < 5) : (i += 1) { | 71 | while (i < 5) : (i += 1) { |
| ... | @@ -92,14 +92,14 @@ fn handleRequest(res: *Server.Response) !void { | ... | @@ -92,14 +92,14 @@ fn handleRequest(res: *Server.Response) !void { |
| 92 | try testing.expectEqualStrings("14", res.request.headers.getFirstValue("content-length").?); | 92 | try testing.expectEqualStrings("14", res.request.headers.getFirstValue("content-length").?); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | try res.do(); | 95 | try res.start(); |
| 96 | try res.writeAll("Hello, "); | 96 | try res.writeAll("Hello, "); |
| 97 | try res.writeAll("World!\n"); | 97 | try res.writeAll("World!\n"); |
| 98 | try res.finish(); | 98 | try res.finish(); |
| 99 | } else if (mem.eql(u8, res.request.target, "/trailer")) { | 99 | } else if (mem.eql(u8, res.request.target, "/trailer")) { |
| 100 | res.transfer_encoding = .chunked; | 100 | res.transfer_encoding = .chunked; |
| 101 | 101 | ||
| 102 | try res.do(); | 102 | try res.start(); |
| 103 | try res.writeAll("Hello, "); | 103 | try res.writeAll("Hello, "); |
| 104 | try res.writeAll("World!\n"); | 104 | try res.writeAll("World!\n"); |
| 105 | // try res.finish(); | 105 | // try res.finish(); |
| ... | @@ -110,7 +110,7 @@ fn handleRequest(res: *Server.Response) !void { | ... | @@ -110,7 +110,7 @@ fn handleRequest(res: *Server.Response) !void { |
| 110 | res.status = .found; | 110 | res.status = .found; |
| 111 | try res.headers.append("location", "../../get"); | 111 | try res.headers.append("location", "../../get"); |
| 112 | 112 | ||
| 113 | try res.do(); | 113 | try res.start(); |
| 114 | try res.writeAll("Hello, "); | 114 | try res.writeAll("Hello, "); |
| 115 | try res.writeAll("Redirected!\n"); | 115 | try res.writeAll("Redirected!\n"); |
| 116 | try res.finish(); | 116 | try res.finish(); |
| ... | @@ -120,7 +120,7 @@ fn handleRequest(res: *Server.Response) !void { | ... | @@ -120,7 +120,7 @@ fn handleRequest(res: *Server.Response) !void { |
| 120 | res.status = .found; | 120 | res.status = .found; |
| 121 | try res.headers.append("location", "/redirect/1"); | 121 | try res.headers.append("location", "/redirect/1"); |
| 122 | 122 | ||
| 123 | try res.do(); | 123 | try res.start(); |
| 124 | try res.writeAll("Hello, "); | 124 | try res.writeAll("Hello, "); |
| 125 | try res.writeAll("Redirected!\n"); | 125 | try res.writeAll("Redirected!\n"); |
| 126 | try res.finish(); | 126 | try res.finish(); |
| ... | @@ -133,7 +133,7 @@ fn handleRequest(res: *Server.Response) !void { | ... | @@ -133,7 +133,7 @@ fn handleRequest(res: *Server.Response) !void { |
| 133 | res.status = .found; | 133 | res.status = .found; |
| 134 | try res.headers.append("location", location); | 134 | try res.headers.append("location", location); |
| 135 | 135 | ||
| 136 | try res.do(); | 136 | try res.start(); |
| 137 | try res.writeAll("Hello, "); | 137 | try res.writeAll("Hello, "); |
| 138 | try res.writeAll("Redirected!\n"); | 138 | try res.writeAll("Redirected!\n"); |
| 139 | try res.finish(); | 139 | try res.finish(); |
| ... | @@ -143,7 +143,7 @@ fn handleRequest(res: *Server.Response) !void { | ... | @@ -143,7 +143,7 @@ fn handleRequest(res: *Server.Response) !void { |
| 143 | res.status = .found; | 143 | res.status = .found; |
| 144 | try res.headers.append("location", "/redirect/3"); | 144 | try res.headers.append("location", "/redirect/3"); |
| 145 | 145 | ||
| 146 | try res.do(); | 146 | try res.start(); |
| 147 | try res.writeAll("Hello, "); | 147 | try res.writeAll("Hello, "); |
| 148 | try res.writeAll("Redirected!\n"); | 148 | try res.writeAll("Redirected!\n"); |
| 149 | try res.finish(); | 149 | try res.finish(); |
| ... | @@ -154,11 +154,11 @@ fn handleRequest(res: *Server.Response) !void { | ... | @@ -154,11 +154,11 @@ fn handleRequest(res: *Server.Response) !void { |
| 154 | 154 | ||
| 155 | res.status = .found; | 155 | res.status = .found; |
| 156 | try res.headers.append("location", location); | 156 | try res.headers.append("location", location); |
| 157 | try res.do(); | 157 | try res.start(); |
| 158 | try res.finish(); | 158 | try res.finish(); |
| 159 | } else { | 159 | } else { |
| 160 | res.status = .not_found; | 160 | res.status = .not_found; |
| 161 | try res.do(); | 161 | try res.start(); |
| 162 | } | 162 | } |
| 163 | } | 163 | } |
| 164 | 164 |