| ... | @@ -44,6 +44,14 @@ https_proxy: ?*Proxy = null, | ... | @@ -44,6 +44,14 @@ https_proxy: ?*Proxy = null, |
| 44 | | 44 | |
| 45 | /// A set of linked lists of connections that can be reused. | 45 | /// A set of linked lists of connections that can be reused. |
| 46 | pub const ConnectionPool = struct { | 46 | pub const ConnectionPool = struct { |
| | 47 | mutex: std.Thread.Mutex = .{}, |
| | 48 | /// Open connections that are currently in use. |
| | 49 | used: Queue = .{}, |
| | 50 | /// Open connections that are not currently in use. |
| | 51 | free: Queue = .{}, |
| | 52 | free_len: usize = 0, |
| | 53 | free_size: usize = 32, |
| | 54 | |
| 47 | /// The criteria for a connection to be considered a match. | 55 | /// The criteria for a connection to be considered a match. |
| 48 | pub const Criteria = struct { | 56 | pub const Criteria = struct { |
| 49 | host: []const u8, | 57 | host: []const u8, |
| ... | @@ -54,14 +62,6 @@ pub const ConnectionPool = struct { | ... | @@ -54,14 +62,6 @@ pub const ConnectionPool = struct { |
| 54 | const Queue = std.DoublyLinkedList(Connection); | 62 | const Queue = std.DoublyLinkedList(Connection); |
| 55 | pub const Node = Queue.Node; | 63 | pub const Node = Queue.Node; |
| 56 | | 64 | |
| 57 | mutex: std.Thread.Mutex = .{}, | | |
| 58 | /// Open connections that are currently in use. | | |
| 59 | used: Queue = .{}, | | |
| 60 | /// Open connections that are not currently in use. | | |
| 61 | free: Queue = .{}, | | |
| 62 | free_len: usize = 0, | | |
| 63 | free_size: usize = 32, | | |
| 64 | | | |
| 65 | /// Finds and acquires a connection from the connection pool matching the criteria. This function is threadsafe. | 65 | /// Finds and acquires a connection from the connection pool matching the criteria. This function is threadsafe. |
| 66 | /// If no connection is found, null is returned. | 66 | /// If no connection is found, null is returned. |
| 67 | pub fn findConnection(pool: *ConnectionPool, criteria: Criteria) ?*Connection { | 67 | pub fn findConnection(pool: *ConnectionPool, criteria: Criteria) ?*Connection { |
| ... | @@ -190,11 +190,6 @@ pub const ConnectionPool = struct { | ... | @@ -190,11 +190,6 @@ pub const ConnectionPool = struct { |
| 190 | | 190 | |
| 191 | /// An interface to either a plain or TLS connection. | 191 | /// An interface to either a plain or TLS connection. |
| 192 | pub const Connection = struct { | 192 | pub const Connection = struct { |
| 193 | pub const buffer_size = std.crypto.tls.max_ciphertext_record_len; | | |
| 194 | const BufferSize = std.math.IntFittingRange(0, buffer_size); | | |
| 195 | | | |
| 196 | pub const Protocol = enum { plain, tls }; | | |
| 197 | | | |
| 198 | stream: net.Stream, | 193 | stream: net.Stream, |
| 199 | /// undefined unless protocol is tls. | 194 | /// undefined unless protocol is tls. |
| 200 | tls_client: if (!disable_tls) *std.crypto.tls.Client else void, | 195 | tls_client: if (!disable_tls) *std.crypto.tls.Client else void, |
| ... | @@ -220,6 +215,11 @@ pub const Connection = struct { | ... | @@ -220,6 +215,11 @@ pub const Connection = struct { |
| 220 | read_buf: [buffer_size]u8 = undefined, | 215 | read_buf: [buffer_size]u8 = undefined, |
| 221 | write_buf: [buffer_size]u8 = undefined, | 216 | write_buf: [buffer_size]u8 = undefined, |
| 222 | | 217 | |
| | 218 | pub const buffer_size = std.crypto.tls.max_ciphertext_record_len; |
| | 219 | const BufferSize = std.math.IntFittingRange(0, buffer_size); |
| | 220 | |
| | 221 | pub const Protocol = enum { plain, tls }; |
| | 222 | |
| 223 | pub fn readvDirectTls(conn: *Connection, buffers: []std.os.iovec) ReadError!usize { | 223 | pub fn readvDirectTls(conn: *Connection, buffers: []std.os.iovec) ReadError!usize { |
| 224 | return conn.tls_client.readv(conn.stream, buffers) catch |err| { | 224 | return conn.tls_client.readv(conn.stream, buffers) catch |err| { |
| 225 | // https://github.com/ziglang/zig/issues/2473 | 225 | // https://github.com/ziglang/zig/issues/2473 |
| ... | @@ -419,6 +419,35 @@ pub const Compression = union(enum) { | ... | @@ -419,6 +419,35 @@ pub const Compression = union(enum) { |
| 419 | | 419 | |
| 420 | /// A HTTP response originating from a server. | 420 | /// A HTTP response originating from a server. |
| 421 | pub const Response = struct { | 421 | pub const Response = struct { |
| | 422 | version: http.Version, |
| | 423 | status: http.Status, |
| | 424 | reason: []const u8, |
| | 425 | |
| | 426 | /// Points into the user-provided `server_header_buffer`. |
| | 427 | location: ?[]const u8 = null, |
| | 428 | /// Points into the user-provided `server_header_buffer`. |
| | 429 | content_type: ?[]const u8 = null, |
| | 430 | /// Points into the user-provided `server_header_buffer`. |
| | 431 | content_disposition: ?[]const u8 = null, |
| | 432 | |
| | 433 | keep_alive: bool = false, |
| | 434 | |
| | 435 | /// If present, the number of bytes in the response body. |
| | 436 | content_length: ?u64 = null, |
| | 437 | |
| | 438 | /// If present, the transfer encoding of the response body, otherwise none. |
| | 439 | transfer_encoding: http.TransferEncoding = .none, |
| | 440 | |
| | 441 | /// If present, the compression of the response body, otherwise identity (no compression). |
| | 442 | transfer_compression: http.ContentEncoding = .identity, |
| | 443 | |
| | 444 | parser: proto.HeadersParser, |
| | 445 | compression: Compression = .none, |
| | 446 | |
| | 447 | /// Whether the response body should be skipped. Any data read from the |
| | 448 | /// response body will be discarded. |
| | 449 | skip: bool = false, |
| | 450 | |
| 422 | pub const ParseError = error{ | 451 | pub const ParseError = error{ |
| 423 | HttpHeadersInvalid, | 452 | HttpHeadersInvalid, |
| 424 | HttpHeaderContinuationsUnsupported, | 453 | HttpHeaderContinuationsUnsupported, |
| ... | @@ -542,35 +571,6 @@ pub const Response = struct { | ... | @@ -542,35 +571,6 @@ pub const Response = struct { |
| 542 | pub fn iterateHeaders(r: Response) proto.HeaderIterator { | 571 | pub fn iterateHeaders(r: Response) proto.HeaderIterator { |
| 543 | return proto.HeaderIterator.init(r.parser.get()); | 572 | return proto.HeaderIterator.init(r.parser.get()); |
| 544 | } | 573 | } |
| 545 | | | |
| 546 | version: http.Version, | | |
| 547 | status: http.Status, | | |
| 548 | reason: []const u8, | | |
| 549 | | | |
| 550 | /// Points into the user-provided `server_header_buffer`. | | |
| 551 | location: ?[]const u8 = null, | | |
| 552 | /// Points into the user-provided `server_header_buffer`. | | |
| 553 | content_type: ?[]const u8 = null, | | |
| 554 | /// Points into the user-provided `server_header_buffer`. | | |
| 555 | content_disposition: ?[]const u8 = null, | | |
| 556 | | | |
| 557 | keep_alive: bool = false, | | |
| 558 | | | |
| 559 | /// If present, the number of bytes in the response body. | | |
| 560 | content_length: ?u64 = null, | | |
| 561 | | | |
| 562 | /// If present, the transfer encoding of the response body, otherwise none. | | |
| 563 | transfer_encoding: http.TransferEncoding = .none, | | |
| 564 | | | |
| 565 | /// If present, the compression of the response body, otherwise identity (no compression). | | |
| 566 | transfer_compression: http.ContentEncoding = .identity, | | |
| 567 | | | |
| 568 | parser: proto.HeadersParser, | | |
| 569 | compression: Compression = .none, | | |
| 570 | | | |
| 571 | /// Whether the response body should be skipped. Any data read from the | | |
| 572 | /// response body will be discarded. | | |
| 573 | skip: bool = false, | | |
| 574 | }; | 574 | }; |
| 575 | | 575 | |
| 576 | /// A HTTP request that has been sent. | 576 | /// A HTTP request that has been sent. |
| ... | @@ -1558,6 +1558,26 @@ pub fn open( | ... | @@ -1558,6 +1558,26 @@ pub fn open( |
| 1558 | } | 1558 | } |
| 1559 | | 1559 | |
| 1560 | pub const FetchOptions = struct { | 1560 | pub const FetchOptions = struct { |
| | 1561 | server_header_buffer: ?[]u8 = null, |
| | 1562 | response_strategy: ResponseStrategy = .{ .storage = .{ .dynamic = 16 * 1024 * 1024 } }, |
| | 1563 | redirect_behavior: ?Request.RedirectBehavior = null, |
| | 1564 | |
| | 1565 | location: Location, |
| | 1566 | method: http.Method = .GET, |
| | 1567 | payload: Payload = .none, |
| | 1568 | raw_uri: bool = false, |
| | 1569 | |
| | 1570 | /// Standard headers that have default, but overridable, behavior. |
| | 1571 | headers: Request.Headers = .{}, |
| | 1572 | /// These headers are kept including when following a redirect to a |
| | 1573 | /// different domain. |
| | 1574 | /// Externally-owned; must outlive the Request. |
| | 1575 | extra_headers: []const http.Header = &.{}, |
| | 1576 | /// These headers are stripped when following a redirect to a different |
| | 1577 | /// domain. |
| | 1578 | /// Externally-owned; must outlive the Request. |
| | 1579 | privileged_headers: []const http.Header = &.{}, |
| | 1580 | |
| 1561 | pub const Location = union(enum) { | 1581 | pub const Location = union(enum) { |
| 1562 | url: []const u8, | 1582 | url: []const u8, |
| 1563 | uri: Uri, | 1583 | uri: Uri, |
| ... | @@ -1587,26 +1607,6 @@ pub const FetchOptions = struct { | ... | @@ -1587,26 +1607,6 @@ pub const FetchOptions = struct { |
| 1587 | /// cannot be returned from `read()`. | 1607 | /// cannot be returned from `read()`. |
| 1588 | static: []u8, | 1608 | static: []u8, |
| 1589 | }; | 1609 | }; |
| 1590 | | | |
| 1591 | server_header_buffer: ?[]u8 = null, | | |
| 1592 | response_strategy: ResponseStrategy = .{ .storage = .{ .dynamic = 16 * 1024 * 1024 } }, | | |
| 1593 | redirect_behavior: ?Request.RedirectBehavior = null, | | |
| 1594 | | | |
| 1595 | location: Location, | | |
| 1596 | method: http.Method = .GET, | | |
| 1597 | payload: Payload = .none, | | |
| 1598 | raw_uri: bool = false, | | |
| 1599 | | | |
| 1600 | /// Standard headers that have default, but overridable, behavior. | | |
| 1601 | headers: Request.Headers = .{}, | | |
| 1602 | /// These headers are kept including when following a redirect to a | | |
| 1603 | /// different domain. | | |
| 1604 | /// Externally-owned; must outlive the Request. | | |
| 1605 | extra_headers: []const http.Header = &.{}, | | |
| 1606 | /// These headers are stripped when following a redirect to a different | | |
| 1607 | /// domain. | | |
| 1608 | /// Externally-owned; must outlive the Request. | | |
| 1609 | privileged_headers: []const http.Header = &.{}, | | |
| 1610 | }; | 1610 | }; |
| 1611 | | 1611 | |
| 1612 | pub const FetchResult = struct { | 1612 | pub const FetchResult = struct { |