diff --git a/lib/std/http/Client.zig b/lib/std/http/Client.zig index b3c0f3e97c..9eb363d752 100644 --- a/lib/std/http/Client.zig +++ b/lib/std/http/Client.zig @@ -605,7 +605,7 @@ pub const Request = struct { raw_uri: bool = false, }; - /// Send the HTTP request to the server. + /// Send the HTTP request headers to the server. pub fn start(req: *Request, options: StartOptions) StartError!void { if (!req.method.requestHasBody() and req.transfer_encoding != .none) return error.UnsupportedTransferEncoding; diff --git a/lib/std/http/Server.zig b/lib/std/http/Server.zig index da53b2b05d..6620433bd4 100644 --- a/lib/std/http/Server.zig +++ b/lib/std/http/Server.zig @@ -14,7 +14,7 @@ allocator: Allocator, socket: net.StreamServer, -/// An interface to either a plain or TLS connection. +/// An interface to a plain connection. pub const Connection = struct { pub const buffer_size = std.crypto.tls.max_ciphertext_record_len; pub const Protocol = enum { plain }; @@ -273,8 +273,13 @@ pub const Request = struct { target: []const u8, version: http.Version, + /// The length of the request body, if known. content_length: ?u64 = null, + + /// The transfer encoding of the request body, or .none if not present. transfer_encoding: http.TransferEncoding = .none, + + /// The compression of the request body, or .identity (no compression) if not present. transfer_compression: http.ContentEncoding = .identity, headers: http.Headers, @@ -311,6 +316,7 @@ pub const Response = struct { finished, }; + /// Free all resources associated with this response. pub fn deinit(res: *Response) void { res.connection.close(); @@ -386,10 +392,10 @@ pub const Response = struct { } } - pub const DoError = Connection.WriteError || error{ UnsupportedTransferEncoding, InvalidContentLength }; + pub const StartError = Connection.WriteError || error{ UnsupportedTransferEncoding, InvalidContentLength }; - /// Send the response headers. - pub fn do(res: *Response) DoError!void { + /// Send the HTTP response headers to the client. + pub fn start(res: *Response) StartError!void { switch (res.state) { .waited => res.state = .responded, .first, .start, .responded, .finished => unreachable, @@ -548,6 +554,7 @@ pub const Response = struct { return .{ .context = res }; } + /// Reads data from the response body. Must be called after `wait`. pub fn read(res: *Response, buffer: []u8) ReadError!usize { switch (res.state) { .waited, .responded, .finished => {}, @@ -583,6 +590,7 @@ pub const Response = struct { return out_index; } + /// Reads data from the response body. Must be called after `wait`. pub fn readAll(res: *Response, buffer: []u8) !usize { var index: usize = 0; while (index < buffer.len) { @@ -602,6 +610,7 @@ pub const Response = struct { } /// Write `bytes` to the server. The `transfer_encoding` request header determines how data will be sent. + /// Must be called after `start` and before `finish`. pub fn write(res: *Response, bytes: []const u8) WriteError!usize { switch (res.state) { .responded => {}, @@ -627,6 +636,8 @@ pub const Response = struct { } } + /// Write `bytes` to the server. The `transfer_encoding` request header determines how data will be sent. + /// Must be called after `start` and before `finish`. pub fn writeAll(req: *Response, bytes: []const u8) WriteError!void { var index: usize = 0; while (index < bytes.len) { @@ -637,6 +648,7 @@ pub const Response = struct { pub const FinishError = WriteError || error{MessageNotCompleted}; /// Finish the body of a request. This notifies the server that you have no more data to send. + /// Must be called after `start`. pub fn finish(res: *Response) FinishError!void { switch (res.state) { .responded => res.state = .finished, @@ -651,6 +663,7 @@ pub const Response = struct { } }; +/// Create a new HTTP server. pub fn init(allocator: Allocator, options: net.StreamServer.Options) Server { return .{ .allocator = allocator, @@ -658,6 +671,7 @@ pub fn init(allocator: Allocator, options: net.StreamServer.Options) Server { }; } +/// Free all resources associated with this server. pub fn deinit(server: *Server) void { server.socket.deinit(); } diff --git a/test/standalone/http.zig b/test/standalone/http.zig index 55a8456fde..a242bb5778 100644 --- a/test/standalone/http.zig +++ b/test/standalone/http.zig @@ -29,11 +29,11 @@ fn handleRequest(res: *Server.Response) !void { if (res.request.headers.contains("expect")) { if (mem.eql(u8, res.request.headers.getFirstValue("expect").?, "100-continue")) { res.status = .@"continue"; - try res.do(); + try res.start(); res.status = .ok; } else { res.status = .expectation_failed; - try res.do(); + try res.start(); return; } } @@ -54,7 +54,7 @@ fn handleRequest(res: *Server.Response) !void { try res.headers.append("content-type", "text/plain"); - try res.do(); + try res.start(); if (res.request.method != .HEAD) { try res.writeAll("Hello, "); try res.writeAll("World!\n"); @@ -65,7 +65,7 @@ fn handleRequest(res: *Server.Response) !void { } else if (mem.startsWith(u8, res.request.target, "/large")) { res.transfer_encoding = .{ .content_length = 14 * 1024 + 14 * 10 }; - try res.do(); + try res.start(); var i: u32 = 0; while (i < 5) : (i += 1) { @@ -92,14 +92,14 @@ fn handleRequest(res: *Server.Response) !void { try testing.expectEqualStrings("14", res.request.headers.getFirstValue("content-length").?); } - try res.do(); + try res.start(); try res.writeAll("Hello, "); try res.writeAll("World!\n"); try res.finish(); } else if (mem.eql(u8, res.request.target, "/trailer")) { res.transfer_encoding = .chunked; - try res.do(); + try res.start(); try res.writeAll("Hello, "); try res.writeAll("World!\n"); // try res.finish(); @@ -110,7 +110,7 @@ fn handleRequest(res: *Server.Response) !void { res.status = .found; try res.headers.append("location", "../../get"); - try res.do(); + try res.start(); try res.writeAll("Hello, "); try res.writeAll("Redirected!\n"); try res.finish(); @@ -120,7 +120,7 @@ fn handleRequest(res: *Server.Response) !void { res.status = .found; try res.headers.append("location", "/redirect/1"); - try res.do(); + try res.start(); try res.writeAll("Hello, "); try res.writeAll("Redirected!\n"); try res.finish(); @@ -133,7 +133,7 @@ fn handleRequest(res: *Server.Response) !void { res.status = .found; try res.headers.append("location", location); - try res.do(); + try res.start(); try res.writeAll("Hello, "); try res.writeAll("Redirected!\n"); try res.finish(); @@ -143,7 +143,7 @@ fn handleRequest(res: *Server.Response) !void { res.status = .found; try res.headers.append("location", "/redirect/3"); - try res.do(); + try res.start(); try res.writeAll("Hello, "); try res.writeAll("Redirected!\n"); try res.finish(); @@ -154,11 +154,11 @@ fn handleRequest(res: *Server.Response) !void { res.status = .found; try res.headers.append("location", location); - try res.do(); + try res.start(); try res.finish(); } else { res.status = .not_found; - try res.do(); + try res.start(); } }