authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-21 17:41:59-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-23 02:37:11-07:00
log51451341bf06f949fd3b4cec0c5c302cecf2aa8c
tree61c13b08ec590e40508f10623080091f8303ef72
parent17291e072b86b7f2bcb775907cf0984e281662a2

update standalone http test file to new API


1 files changed, 109 insertions(+), 117 deletions(-)

test/standalone/http.zig+109-117
...@@ -17,150 +17,145 @@ var gpa_client = std.heap.GeneralPurposeAllocator(.{ .stack_trace_frames = 12 })...@@ -17,150 +17,145 @@ var gpa_client = std.heap.GeneralPurposeAllocator(.{ .stack_trace_frames = 12 })
17const salloc = gpa_server.allocator();17const salloc = gpa_server.allocator();
18const calloc = gpa_client.allocator();18const calloc = gpa_client.allocator();
1919
20fn handleRequest(res: *http.Server, listen_port: u16) !void {20fn handleRequest(request: *http.Server.Request, listen_port: u16) !void {
21 const log = std.log.scoped(.server);21 const log = std.log.scoped(.server);
2222
23 log.info("{} {s} {s}", .{ res.request.method, @tagName(res.request.version), res.request.target });23 log.info("{} {s} {s}", .{
24 request.head.method,
25 @tagName(request.head.version),
26 request.head.target,
27 });
2428
25 if (res.request.expect) |expect| {29 if (request.head.expect) |expect| {
26 if (mem.eql(u8, expect, "100-continue")) {30 if (mem.eql(u8, expect, "100-continue")) {
27 res.status = .@"continue";31 @panic("test failure, didn't handle expect 100-continue");
28 try res.send();
29 res.status = .ok;
30 } else {32 } else {
31 res.status = .expectation_failed;33 return request.respond("", .{
32 try res.send();34 .status = .expectation_failed,
33 return;35 });
34 }36 }
35 }37 }
3638
37 const body = try res.reader().readAllAlloc(salloc, 8192);39 const body = try request.reader().readAllAlloc(salloc, 8192);
38 defer salloc.free(body);40 defer salloc.free(body);
3941
40 if (res.request.keep_alive) {42 var send_buffer: [100]u8 = undefined;
41 res.keep_alive = true;43
42 }44 if (mem.startsWith(u8, request.head.target, "/get")) {
4345 var response = request.respondStreaming(.{
44 if (mem.startsWith(u8, res.request.target, "/get")) {46 .send_buffer = &send_buffer,
45 if (std.mem.indexOf(u8, res.request.target, "?chunked") != null) {47 .content_length = if (std.mem.indexOf(u8, request.head.target, "?chunked") == null)
46 res.transfer_encoding = .chunked;48 14
47 } else {49 else
48 res.transfer_encoding = .{ .content_length = 14 };50 null,
49 }51 .respond_options = .{
52 .extra_headers = &.{
53 .{ .name = "content-type", .value = "text/plain" },
54 },
55 },
56 });
57 const w = response.writer();
58 try w.writeAll("Hello, ");
59 try w.writeAll("World!\n");
60 try response.end();
61 // Writing again would cause an assertion failure.
62 } else if (mem.startsWith(u8, request.head.target, "/large")) {
63 var response = request.respondStreaming(.{
64 .send_buffer = &send_buffer,
65 .content_length = 14 * 1024 + 14 * 10,
66 });
5067
51 res.extra_headers = &.{68 try response.flush(); // Test an early flush to send the HTTP headers before the body.
52 .{ .name = "content-type", .value = "text/plain" },
53 };
5469
55 try res.send();70 const w = response.writer();
56 if (res.request.method != .HEAD) {
57 try res.writeAll("Hello, ");
58 try res.writeAll("World!\n");
59 try res.finish();
60 } else {
61 try testing.expectEqual(res.writeAll("errors"), error.NotWriteable);
62 }
63 } else if (mem.startsWith(u8, res.request.target, "/large")) {
64 res.transfer_encoding = .{ .content_length = 14 * 1024 + 14 * 10 };
65
66 try res.send();
6771
68 var i: u32 = 0;72 var i: u32 = 0;
69 while (i < 5) : (i += 1) {73 while (i < 5) : (i += 1) {
70 try res.writeAll("Hello, World!\n");74 try w.writeAll("Hello, World!\n");
71 }75 }
7276
73 try res.writeAll("Hello, World!\n" ** 1024);77 try w.writeAll("Hello, World!\n" ** 1024);
7478
75 i = 0;79 i = 0;
76 while (i < 5) : (i += 1) {80 while (i < 5) : (i += 1) {
77 try res.writeAll("Hello, World!\n");81 try w.writeAll("Hello, World!\n");
78 }82 }
7983
80 try res.finish();84 try response.end();
81 } else if (mem.startsWith(u8, res.request.target, "/echo-content")) {85 } else if (mem.startsWith(u8, request.head.target, "/echo-content")) {
82 try testing.expectEqualStrings("Hello, World!\n", body);86 try testing.expectEqualStrings("Hello, World!\n", body);
83 try testing.expectEqualStrings("text/plain", res.request.content_type.?);87 try testing.expectEqualStrings("text/plain", request.head.content_type.?);
8488
85 switch (res.request.transfer_encoding) {89 var response = request.respondStreaming(.{
86 .chunked => res.transfer_encoding = .chunked,90 .send_buffer = &send_buffer,
87 .none => {91 .content_length = switch (request.head.transfer_encoding) {
88 res.transfer_encoding = .{ .content_length = 14 };92 .chunked => null,
89 try testing.expectEqual(14, res.request.content_length.?);93 .none => len: {
94 try testing.expectEqual(14, request.head.content_length.?);
95 break :len 14;
96 },
90 },97 },
91 }98 });
92
93 try res.send();
94 try res.writeAll("Hello, ");
95 try res.writeAll("World!\n");
96 try res.finish();
97 } else if (mem.eql(u8, res.request.target, "/redirect/1")) {
98 res.transfer_encoding = .chunked;
99
100 res.status = .found;
101 res.extra_headers = &.{
102 .{ .name = "location", .value = "../../get" },
103 };
104
105 try res.send();
106 try res.writeAll("Hello, ");
107 try res.writeAll("Redirected!\n");
108 try res.finish();
109 } else if (mem.eql(u8, res.request.target, "/redirect/2")) {
110 res.transfer_encoding = .chunked;
111
112 res.status = .found;
113 res.extra_headers = &.{
114 .{ .name = "location", .value = "/redirect/1" },
115 };
11699
117 try res.send();100 try response.flush(); // Test an early flush to send the HTTP headers before the body.
118 try res.writeAll("Hello, ");101 const w = response.writer();
119 try res.writeAll("Redirected!\n");102 try w.writeAll("Hello, ");
120 try res.finish();103 try w.writeAll("World!\n");
121 } else if (mem.eql(u8, res.request.target, "/redirect/3")) {104 try response.end();
122 res.transfer_encoding = .chunked;105 } else if (mem.eql(u8, request.head.target, "/redirect/1")) {
106 var response = request.respondStreaming(.{
107 .send_buffer = &send_buffer,
108 .respond_options = .{
109 .status = .found,
110 .extra_headers = &.{
111 .{ .name = "location", .value = "../../get" },
112 },
113 },
114 });
123115
116 const w = response.writer();
117 try w.writeAll("Hello, ");
118 try w.writeAll("Redirected!\n");
119 try response.end();
120 } else if (mem.eql(u8, request.head.target, "/redirect/2")) {
121 try request.respond("Hello, Redirected!\n", .{
122 .status = .found,
123 .extra_headers = &.{
124 .{ .name = "location", .value = "/redirect/1" },
125 },
126 });
127 } else if (mem.eql(u8, request.head.target, "/redirect/3")) {
124 const location = try std.fmt.allocPrint(salloc, "http://127.0.0.1:{d}/redirect/2", .{128 const location = try std.fmt.allocPrint(salloc, "http://127.0.0.1:{d}/redirect/2", .{
125 listen_port,129 listen_port,
126 });130 });
127 defer salloc.free(location);131 defer salloc.free(location);
128132
129 res.status = .found;133 try request.respond("Hello, Redirected!\n", .{
130 res.extra_headers = &.{134 .status = .found,
131 .{ .name = "location", .value = location },135 .extra_headers = &.{
132 };136 .{ .name = "location", .value = location },
133137 },
134 try res.send();138 });
135 try res.writeAll("Hello, ");139 } else if (mem.eql(u8, request.head.target, "/redirect/4")) {
136 try res.writeAll("Redirected!\n");140 try request.respond("Hello, Redirected!\n", .{
137 try res.finish();141 .status = .found,
138 } else if (mem.eql(u8, res.request.target, "/redirect/4")) {142 .extra_headers = &.{
139 res.transfer_encoding = .chunked;143 .{ .name = "location", .value = "/redirect/3" },
140144 },
141 res.status = .found;145 });
142 res.extra_headers = &.{146 } else if (mem.eql(u8, request.head.target, "/redirect/invalid")) {
143 .{ .name = "location", .value = "/redirect/3" },
144 };
145
146 try res.send();
147 try res.writeAll("Hello, ");
148 try res.writeAll("Redirected!\n");
149 try res.finish();
150 } else if (mem.eql(u8, res.request.target, "/redirect/invalid")) {
151 const invalid_port = try getUnusedTcpPort();147 const invalid_port = try getUnusedTcpPort();
152 const location = try std.fmt.allocPrint(salloc, "http://127.0.0.1:{d}", .{invalid_port});148 const location = try std.fmt.allocPrint(salloc, "http://127.0.0.1:{d}", .{invalid_port});
153 defer salloc.free(location);149 defer salloc.free(location);
154150
155 res.status = .found;151 try request.respond("", .{
156 res.extra_headers = &.{152 .status = .found,
157 .{ .name = "location", .value = location },153 .extra_headers = &.{
158 };154 .{ .name = "location", .value = location },
159 try res.send();155 },
160 try res.finish();156 });
161 } else {157 } else {
162 res.status = .not_found;158 try request.respond("", .{ .status = .not_found });
163 try res.send();
164 }159 }
165}160}
166161
...@@ -172,18 +167,15 @@ fn runServer(server: *std.net.Server) !void {...@@ -172,18 +167,15 @@ fn runServer(server: *std.net.Server) !void {
172 var connection = try server.accept();167 var connection = try server.accept();
173 defer connection.stream.close();168 defer connection.stream.close();
174169
175 var res = http.Server.init(connection, .{170 var http_server = http.Server.init(connection, &client_header_buffer);
176 .client_header_buffer = &client_header_buffer,
177 });
178171
179 while (res.reset() != .closing) {172 while (http_server.state == .ready) {
180 res.wait() catch |err| switch (err) {173 var request = http_server.receiveHead() catch |err| switch (err) {
181 error.HttpHeadersInvalid => continue :outer,174 error.HttpConnectionClosing => continue :outer,
182 error.EndOfStream => continue,175 else => |e| return e,
183 else => return err,
184 };176 };
185177
186 try handleRequest(&res, server.listen_address.getPort());178 try handleRequest(&request, server.listen_address.getPort());
187 }179 }
188 }180 }
189}181}