authorgravatar for truemedian@gmail.comNameless <truemedian@gmail.com> 2023-10-07 20:05:04-05:00
committergravatar for truemedian@gmail.comNameless <truemedian@gmail.com> 2023-10-21 20:52:59-05:00
log544ed34d99f59a1b487341eaaa9610be44629924
tree4e14e3404ac1d3eb0ea12fcbd6b7b040a0c9cfb3
parentd4cf8ea0b7621f7757203ecdbaa760e99cbc455c
signaturelock-open Commit is signed but in an unrecognized format.

std.http.Server: improve documentation, do -> start

Response.do was renamed to Response.start to mimic the naming scheme in http.Client

3 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 };
607607
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;
611611
lib/std/http/Server.zig+18-4
...@@ -14,7 +14,7 @@ allocator: Allocator,...@@ -14,7 +14,7 @@ allocator: Allocator,
1414
15socket: net.StreamServer,15socket: net.StreamServer,
1616
17/// An interface to either a plain or TLS connection.17/// An interface to a plain connection.
18pub const Connection = struct {18pub 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,
275275
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,
279284
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 };
313318
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();
316322
...@@ -386,10 +392,10 @@ pub const Response = struct {...@@ -386,10 +392,10 @@ pub const Response = struct {
386 }392 }
387 }393 }
388394
389 pub const DoError = Connection.WriteError || error{ UnsupportedTransferEncoding, InvalidContentLength };395 pub const StartError = Connection.WriteError || error{ UnsupportedTransferEncoding, InvalidContentLength };
390396
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 }
550556
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 }
585592
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 }
603611
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 }
629638
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};
638649
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};
653665
666/// Create a new HTTP server.
654pub fn init(allocator: Allocator, options: net.StreamServer.Options) Server {667pub 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}
660673
674/// Free all resources associated with this server.
661pub fn deinit(server: *Server) void {675pub 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 {
5454
55 try res.headers.append("content-type", "text/plain");55 try res.headers.append("content-type", "text/plain");
5656
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 };
6767
68 try res.do();68 try res.start();
6969
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 }
9494
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;
101101
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");
112112
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");
122122
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);
135135
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");
145145
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 {
154154
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}
164164