| ... | ... | @@ -352,7 +352,7 @@ pub const Response = struct { |
| 352 | 352 | |
| 353 | 353 | transfer_encoding: ResponseTransfer = .none, |
| 354 | 354 | |
| 355 | | server: *Server, |
| 355 | allocator: Allocator, |
| 356 | 356 | address: net.Address, |
| 357 | 357 | connection: BufferedConnection, |
| 358 | 358 | |
| ... | ... | @@ -376,7 +376,7 @@ pub const Response = struct { |
| 376 | 376 | res.request.headers.deinit(); |
| 377 | 377 | |
| 378 | 378 | if (res.request.parser.header_bytes_owned) { |
| 379 | | res.request.parser.header_bytes.deinit(res.server.allocator); |
| 379 | res.request.parser.header_bytes.deinit(res.allocator); |
| 380 | 380 | } |
| 381 | 381 | } |
| 382 | 382 | |
| ... | ... | @@ -545,13 +545,13 @@ pub const Response = struct { |
| 545 | 545 | while (true) { |
| 546 | 546 | try res.connection.fill(); |
| 547 | 547 | |
| 548 | | const nchecked = try res.request.parser.checkCompleteHead(res.server.allocator, res.connection.peek()); |
| 548 | const nchecked = try res.request.parser.checkCompleteHead(res.allocator, res.connection.peek()); |
| 549 | 549 | res.connection.clear(@intCast(u16, nchecked)); |
| 550 | 550 | |
| 551 | 551 | if (res.request.parser.state.isContent()) break; |
| 552 | 552 | } |
| 553 | 553 | |
| 554 | | res.request.headers = .{ .allocator = res.server.allocator, .owned = true }; |
| 554 | res.request.headers = .{ .allocator = res.allocator, .owned = true }; |
| 555 | 555 | try res.request.parse(res.request.parser.header_bytes.items); |
| 556 | 556 | |
| 557 | 557 | if (res.request.transfer_encoding) |te| { |
| ... | ... | @@ -573,13 +573,13 @@ pub const Response = struct { |
| 573 | 573 | if (res.request.transfer_compression) |tc| switch (tc) { |
| 574 | 574 | .compress => return error.CompressionNotSupported, |
| 575 | 575 | .deflate => res.request.compression = .{ |
| 576 | | .deflate = std.compress.zlib.zlibStream(res.server.allocator, res.transferReader()) catch return error.CompressionInitializationFailed, |
| 576 | .deflate = std.compress.zlib.zlibStream(res.allocator, res.transferReader()) catch return error.CompressionInitializationFailed, |
| 577 | 577 | }, |
| 578 | 578 | .gzip => res.request.compression = .{ |
| 579 | | .gzip = std.compress.gzip.decompress(res.server.allocator, res.transferReader()) catch return error.CompressionInitializationFailed, |
| 579 | .gzip = std.compress.gzip.decompress(res.allocator, res.transferReader()) catch return error.CompressionInitializationFailed, |
| 580 | 580 | }, |
| 581 | 581 | .zstd => res.request.compression = .{ |
| 582 | | .zstd = std.compress.zstd.decompressStream(res.server.allocator, res.transferReader()), |
| 582 | .zstd = std.compress.zstd.decompressStream(res.allocator, res.transferReader()), |
| 583 | 583 | }, |
| 584 | 584 | }; |
| 585 | 585 | } |
| ... | ... | @@ -612,12 +612,12 @@ pub const Response = struct { |
| 612 | 612 | while (!res.request.parser.state.isContent()) { // read trailing headers |
| 613 | 613 | try res.connection.fill(); |
| 614 | 614 | |
| 615 | | const nchecked = try res.request.parser.checkCompleteHead(res.server.allocator, res.connection.peek()); |
| 615 | const nchecked = try res.request.parser.checkCompleteHead(res.allocator, res.connection.peek()); |
| 616 | 616 | res.connection.clear(@intCast(u16, nchecked)); |
| 617 | 617 | } |
| 618 | 618 | |
| 619 | 619 | if (has_trail) { |
| 620 | | res.request.headers = http.Headers{ .allocator = res.server.allocator, .owned = false }; |
| 620 | res.request.headers = http.Headers{ .allocator = res.allocator, .owned = false }; |
| 621 | 621 | |
| 622 | 622 | // The response headers before the trailers are already guaranteed to be valid, so they will always be parsed again and cannot return an error. |
| 623 | 623 | // This will *only* fail for a malformed trailer. |
| ... | ... | @@ -731,24 +731,29 @@ pub const HeaderStrategy = union(enum) { |
| 731 | 731 | static: []u8, |
| 732 | 732 | }; |
| 733 | 733 | |
| 734 | pub const AcceptOptions = struct { |
| 735 | allocator: Allocator, |
| 736 | header_strategy: HeaderStrategy = .{ .dynamic = 8192 }, |
| 737 | }; |
| 738 | |
| 734 | 739 | /// Accept a new connection. |
| 735 | | pub fn accept(server: *Server, options: HeaderStrategy) AcceptError!Response { |
| 740 | pub fn accept(server: *Server, options: AcceptOptions) AcceptError!Response { |
| 736 | 741 | const in = try server.socket.accept(); |
| 737 | 742 | |
| 738 | 743 | return Response{ |
| 739 | | .server = server, |
| 744 | .allocator = options.allocator, |
| 740 | 745 | .address = in.address, |
| 741 | 746 | .connection = .{ .conn = .{ |
| 742 | 747 | .stream = in.stream, |
| 743 | 748 | .protocol = .plain, |
| 744 | 749 | } }, |
| 745 | | .headers = .{ .allocator = server.allocator }, |
| 750 | .headers = .{ .allocator = options.allocator }, |
| 746 | 751 | .request = .{ |
| 747 | 752 | .version = undefined, |
| 748 | 753 | .method = undefined, |
| 749 | 754 | .target = undefined, |
| 750 | | .headers = .{ .allocator = server.allocator, .owned = false }, |
| 751 | | .parser = switch (options) { |
| 755 | .headers = .{ .allocator = options.allocator, .owned = false }, |
| 756 | .parser = switch (options.header_strategy) { |
| 752 | 757 | .dynamic => |max| proto.HeadersParser.initDynamic(max), |
| 753 | 758 | .static => |buf| proto.HeadersParser.initStatic(buf), |
| 754 | 759 | }, |