| ... | ... | @@ -9,8 +9,8 @@ const testing = std.testing; |
| 9 | 9 | |
| 10 | 10 | const max_header_size = 8192; |
| 11 | 11 | |
| 12 | | var gpa_server = std.heap.GeneralPurposeAllocator(.{}){}; |
| 13 | | var gpa_client = std.heap.GeneralPurposeAllocator(.{}){}; |
| 12 | var gpa_server = std.heap.GeneralPurposeAllocator(.{ .stack_trace_frames = 12 }){}; |
| 13 | var gpa_client = std.heap.GeneralPurposeAllocator(.{ .stack_trace_frames = 12 }){}; |
| 14 | 14 | |
| 15 | 15 | const salloc = gpa_server.allocator(); |
| 16 | 16 | const calloc = gpa_client.allocator(); |
| ... | ... | @@ -44,6 +44,24 @@ fn handleRequest(res: *Server.Response) !void { |
| 44 | 44 | try res.writeAll("World!\n"); |
| 45 | 45 | try res.finish(); |
| 46 | 46 | } |
| 47 | } else if (mem.startsWith(u8, res.request.target, "/large")) { |
| 48 | res.transfer_encoding = .{ .content_length = 14 * 1024 + 14 * 10 }; |
| 49 | |
| 50 | try res.do(); |
| 51 | |
| 52 | var i: u32 = 0; |
| 53 | while (i < 5) : (i += 1) { |
| 54 | try res.writeAll("Hello, World!\n"); |
| 55 | } |
| 56 | |
| 57 | try res.writeAll("Hello, World!\n" ** 1024); |
| 58 | |
| 59 | i = 0; |
| 60 | while (i < 5) : (i += 1) { |
| 61 | try res.writeAll("Hello, World!\n"); |
| 62 | } |
| 63 | |
| 64 | try res.finish(); |
| 47 | 65 | } else if (mem.eql(u8, res.request.target, "/echo-content")) { |
| 48 | 66 | try testing.expectEqualStrings("Hello, World!\n", body); |
| 49 | 67 | try testing.expectEqualStrings("text/plain", res.request.headers.getFirstValue("content-type").?); |
| ... | ... | @@ -68,6 +86,7 @@ fn handleRequest(res: *Server.Response) !void { |
| 68 | 86 | try res.writeAll("World!\n"); |
| 69 | 87 | // try res.finish(); |
| 70 | 88 | try res.connection.writeAll("0\r\nX-Checksum: aaaa\r\n\r\n"); |
| 89 | try res.connection.flush(); |
| 71 | 90 | } else if (mem.eql(u8, res.request.target, "/redirect/1")) { |
| 72 | 91 | res.transfer_encoding = .chunked; |
| 73 | 92 | |
| ... | ... | @@ -177,8 +196,7 @@ pub fn main() !void { |
| 177 | 196 | const server_thread = try std.Thread.spawn(.{}, serverThread, .{&server}); |
| 178 | 197 | |
| 179 | 198 | var client = Client{ .allocator = calloc }; |
| 180 | | |
| 181 | | defer client.deinit(); |
| 199 | // defer client.deinit(); handled below |
| 182 | 200 | |
| 183 | 201 | { // read content-length response |
| 184 | 202 | var h = http.Headers{ .allocator = calloc }; |
| ... | ... | @@ -202,6 +220,33 @@ pub fn main() !void { |
| 202 | 220 | try testing.expectEqualStrings("text/plain", req.response.headers.getFirstValue("content-type").?); |
| 203 | 221 | } |
| 204 | 222 | |
| 223 | // connection has been kept alive |
| 224 | try testing.expect(client.connection_pool.free_len == 1); |
| 225 | |
| 226 | { // read large content-length response |
| 227 | var h = http.Headers{ .allocator = calloc }; |
| 228 | defer h.deinit(); |
| 229 | |
| 230 | const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/large", .{port}); |
| 231 | defer calloc.free(location); |
| 232 | const uri = try std.Uri.parse(location); |
| 233 | |
| 234 | log.info("{s}", .{location}); |
| 235 | var req = try client.request(.GET, uri, h, .{}); |
| 236 | defer req.deinit(); |
| 237 | |
| 238 | try req.start(); |
| 239 | try req.wait(); |
| 240 | |
| 241 | const body = try req.reader().readAllAlloc(calloc, 8192 * 1024); |
| 242 | defer calloc.free(body); |
| 243 | |
| 244 | try testing.expectEqual(@as(usize, 14 * 1024 + 14 * 10), body.len); |
| 245 | } |
| 246 | |
| 247 | // connection has been kept alive |
| 248 | try testing.expect(client.connection_pool.free_len == 1); |
| 249 | |
| 205 | 250 | { // send head request and not read chunked |
| 206 | 251 | var h = http.Headers{ .allocator = calloc }; |
| 207 | 252 | defer h.deinit(); |
| ... | ... | @@ -225,6 +270,9 @@ pub fn main() !void { |
| 225 | 270 | try testing.expectEqualStrings("14", req.response.headers.getFirstValue("content-length").?); |
| 226 | 271 | } |
| 227 | 272 | |
| 273 | // connection has been kept alive |
| 274 | try testing.expect(client.connection_pool.free_len == 1); |
| 275 | |
| 228 | 276 | { // read chunked response |
| 229 | 277 | var h = http.Headers{ .allocator = calloc }; |
| 230 | 278 | defer h.deinit(); |
| ... | ... | @@ -247,6 +295,9 @@ pub fn main() !void { |
| 247 | 295 | try testing.expectEqualStrings("text/plain", req.response.headers.getFirstValue("content-type").?); |
| 248 | 296 | } |
| 249 | 297 | |
| 298 | // connection has been kept alive |
| 299 | try testing.expect(client.connection_pool.free_len == 1); |
| 300 | |
| 250 | 301 | { // send head request and not read chunked |
| 251 | 302 | var h = http.Headers{ .allocator = calloc }; |
| 252 | 303 | defer h.deinit(); |
| ... | ... | @@ -270,6 +321,9 @@ pub fn main() !void { |
| 270 | 321 | try testing.expectEqualStrings("chunked", req.response.headers.getFirstValue("transfer-encoding").?); |
| 271 | 322 | } |
| 272 | 323 | |
| 324 | // connection has been kept alive |
| 325 | try testing.expect(client.connection_pool.free_len == 1); |
| 326 | |
| 273 | 327 | { // check trailing headers |
| 274 | 328 | var h = http.Headers{ .allocator = calloc }; |
| 275 | 329 | defer h.deinit(); |
| ... | ... | @@ -292,6 +346,9 @@ pub fn main() !void { |
| 292 | 346 | try testing.expectEqualStrings("aaaa", req.response.headers.getFirstValue("x-checksum").?); |
| 293 | 347 | } |
| 294 | 348 | |
| 349 | // connection has been kept alive |
| 350 | try testing.expect(client.connection_pool.free_len == 1); |
| 351 | |
| 295 | 352 | { // send content-length request |
| 296 | 353 | var h = http.Headers{ .allocator = calloc }; |
| 297 | 354 | defer h.deinit(); |
| ... | ... | @@ -321,6 +378,36 @@ pub fn main() !void { |
| 321 | 378 | try testing.expectEqualStrings("Hello, World!\n", body); |
| 322 | 379 | } |
| 323 | 380 | |
| 381 | // connection has been kept alive |
| 382 | try testing.expect(client.connection_pool.free_len == 1); |
| 383 | |
| 384 | { // read content-length response with connection close |
| 385 | var h = http.Headers{ .allocator = calloc }; |
| 386 | defer h.deinit(); |
| 387 | |
| 388 | try h.append("connection", "close"); |
| 389 | |
| 390 | const location = try std.fmt.allocPrint(calloc, "http://127.0.0.1:{d}/get", .{port}); |
| 391 | defer calloc.free(location); |
| 392 | const uri = try std.Uri.parse(location); |
| 393 | |
| 394 | log.info("{s}", .{location}); |
| 395 | var req = try client.request(.GET, uri, h, .{}); |
| 396 | defer req.deinit(); |
| 397 | |
| 398 | try req.start(); |
| 399 | try req.wait(); |
| 400 | |
| 401 | const body = try req.reader().readAllAlloc(calloc, 8192); |
| 402 | defer calloc.free(body); |
| 403 | |
| 404 | try testing.expectEqualStrings("Hello, World!\n", body); |
| 405 | try testing.expectEqualStrings("text/plain", req.response.headers.getFirstValue("content-type").?); |
| 406 | } |
| 407 | |
| 408 | // connection has been closed |
| 409 | try testing.expect(client.connection_pool.free_len == 0); |
| 410 | |
| 324 | 411 | { // send chunked request |
| 325 | 412 | var h = http.Headers{ .allocator = calloc }; |
| 326 | 413 | defer h.deinit(); |
| ... | ... | @@ -350,6 +437,9 @@ pub fn main() !void { |
| 350 | 437 | try testing.expectEqualStrings("Hello, World!\n", body); |
| 351 | 438 | } |
| 352 | 439 | |
| 440 | // connection has been kept alive |
| 441 | try testing.expect(client.connection_pool.free_len == 1); |
| 442 | |
| 353 | 443 | { // relative redirect |
| 354 | 444 | var h = http.Headers{ .allocator = calloc }; |
| 355 | 445 | defer h.deinit(); |
| ... | ... | @@ -371,6 +461,9 @@ pub fn main() !void { |
| 371 | 461 | try testing.expectEqualStrings("Hello, World!\n", body); |
| 372 | 462 | } |
| 373 | 463 | |
| 464 | // connection has been kept alive |
| 465 | try testing.expect(client.connection_pool.free_len == 1); |
| 466 | |
| 374 | 467 | { // redirect from root |
| 375 | 468 | var h = http.Headers{ .allocator = calloc }; |
| 376 | 469 | defer h.deinit(); |
| ... | ... | @@ -392,6 +485,9 @@ pub fn main() !void { |
| 392 | 485 | try testing.expectEqualStrings("Hello, World!\n", body); |
| 393 | 486 | } |
| 394 | 487 | |
| 488 | // connection has been kept alive |
| 489 | try testing.expect(client.connection_pool.free_len == 1); |
| 490 | |
| 395 | 491 | { // absolute redirect |
| 396 | 492 | var h = http.Headers{ .allocator = calloc }; |
| 397 | 493 | defer h.deinit(); |
| ... | ... | @@ -413,6 +509,9 @@ pub fn main() !void { |
| 413 | 509 | try testing.expectEqualStrings("Hello, World!\n", body); |
| 414 | 510 | } |
| 415 | 511 | |
| 512 | // connection has been kept alive |
| 513 | try testing.expect(client.connection_pool.free_len == 1); |
| 514 | |
| 416 | 515 | { // too many redirects |
| 417 | 516 | var h = http.Headers{ .allocator = calloc }; |
| 418 | 517 | defer h.deinit(); |
| ... | ... | @@ -432,6 +531,11 @@ pub fn main() !void { |
| 432 | 531 | }; |
| 433 | 532 | } |
| 434 | 533 | |
| 534 | // connection has been kept alive |
| 535 | try testing.expect(client.connection_pool.free_len == 1); |
| 536 | |
| 537 | client.deinit(); |
| 538 | |
| 435 | 539 | killServer(server.socket.listen_address); |
| 436 | 540 | server_thread.join(); |
| 437 | 541 | } |