| ... | @@ -218,7 +218,17 @@ pub const Connection = struct { | ... | @@ -218,7 +218,17 @@ pub const Connection = struct { |
| 218 | pub const buffer_size = std.crypto.tls.max_ciphertext_record_len; | 218 | pub const buffer_size = std.crypto.tls.max_ciphertext_record_len; |
| 219 | const BufferSize = std.math.IntFittingRange(0, buffer_size); | 219 | const BufferSize = std.math.IntFittingRange(0, buffer_size); |
| 220 | | 220 | |
| 221 | pub const Protocol = enum { plain, tls }; | 221 | pub const Protocol = enum { |
| | 222 | plain, |
| | 223 | tls, |
| | 224 | |
| | 225 | pub fn port(p: Protocol) u16 { |
| | 226 | return switch (p) { |
| | 227 | .plain => 80, |
| | 228 | .tls => 443, |
| | 229 | }; |
| | 230 | } |
| | 231 | }; |
| 222 | | 232 | |
| 223 | pub fn readvDirectTls(conn: *Connection, buffers: []std.posix.iovec) ReadError!usize { | 233 | pub fn readvDirectTls(conn: *Connection, buffers: []std.posix.iovec) ReadError!usize { |
| 224 | return conn.tls_client.readv(conn.stream, buffers) catch |err| { | 234 | return conn.tls_client.readv(conn.stream, buffers) catch |err| { |
| ... | @@ -805,7 +815,7 @@ pub const Request = struct { | ... | @@ -805,7 +815,7 @@ pub const Request = struct { |
| 805 | } | 815 | } |
| 806 | | 816 | |
| 807 | req.uri = valid_uri; | 817 | req.uri = valid_uri; |
| 808 | req.connection = try req.client.connect(new_host, uriPort(valid_uri, protocol), protocol); | 818 | req.connection = try req.client.connect(new_host, valid_uri.port.?, protocol); |
| 809 | req.redirect_behavior.subtractOne(); | 819 | req.redirect_behavior.subtractOne(); |
| 810 | req.response.parser.reset(); | 820 | req.response.parser.reset(); |
| 811 | | 821 | |
| ... | @@ -847,8 +857,13 @@ pub const Request = struct { | ... | @@ -847,8 +857,13 @@ pub const Request = struct { |
| 847 | try w.writeAll("\r\n"); | 857 | try w.writeAll("\r\n"); |
| 848 | | 858 | |
| 849 | if (try emitOverridableHeader("host: ", req.headers.host, w)) { | 859 | if (try emitOverridableHeader("host: ", req.headers.host, w)) { |
| | 860 | // URI has already been validated so this cannot fail. |
| | 861 | const default_port = (uriProtocol(req.uri) catch unreachable).port(); |
| 850 | try w.writeAll("host: "); | 862 | try w.writeAll("host: "); |
| 851 | try req.uri.writeToStream(.{ .authority = true }, w); | 863 | try req.uri.writeToStream(.{ |
| | 864 | .authority = true, |
| | 865 | .port = req.uri.port.? != default_port, |
| | 866 | }, w); |
| 852 | try w.writeAll("\r\n"); | 867 | try w.writeAll("\r\n"); |
| 853 | } | 868 | } |
| 854 | | 869 | |
| ... | @@ -1264,7 +1279,7 @@ fn createProxyFromEnvVar(arena: Allocator, env_var_names: []const []const u8) !? | ... | @@ -1264,7 +1279,7 @@ fn createProxyFromEnvVar(arena: Allocator, env_var_names: []const []const u8) !? |
| 1264 | .protocol = protocol, | 1279 | .protocol = protocol, |
| 1265 | .host = valid_uri.host.?.raw, | 1280 | .host = valid_uri.host.?.raw, |
| 1266 | .authorization = authorization, | 1281 | .authorization = authorization, |
| 1267 | .port = uriPort(valid_uri, protocol), | 1282 | .port = valid_uri.port.?, |
| 1268 | .supports_connect = true, | 1283 | .supports_connect = true, |
| 1269 | }; | 1284 | }; |
| 1270 | return proxy; | 1285 | return proxy; |
| ... | @@ -1569,29 +1584,27 @@ pub const RequestOptions = struct { | ... | @@ -1569,29 +1584,27 @@ pub const RequestOptions = struct { |
| 1569 | privileged_headers: []const http.Header = &.{}, | 1584 | privileged_headers: []const http.Header = &.{}, |
| 1570 | }; | 1585 | }; |
| 1571 | | 1586 | |
| 1572 | fn validateUri(uri: Uri, arena: Allocator) !struct { Connection.Protocol, Uri } { | 1587 | fn uriProtocol(uri: Uri) !Connection.Protocol { |
| 1573 | const protocol_map = std.ComptimeStringMap(Connection.Protocol, .{ | 1588 | const protocol_map = std.ComptimeStringMap(Connection.Protocol, .{ |
| 1574 | .{ "http", .plain }, | 1589 | .{ "http", .plain }, |
| 1575 | .{ "ws", .plain }, | 1590 | .{ "ws", .plain }, |
| 1576 | .{ "https", .tls }, | 1591 | .{ "https", .tls }, |
| 1577 | .{ "wss", .tls }, | 1592 | .{ "wss", .tls }, |
| 1578 | }); | 1593 | }); |
| 1579 | const protocol = protocol_map.get(uri.scheme) orelse return error.UnsupportedUriScheme; | 1594 | return protocol_map.get(uri.scheme) orelse return error.UnsupportedUriScheme; |
| | 1595 | } |
| | 1596 | |
| | 1597 | fn validateUri(uri: Uri, arena: Allocator) !struct { Connection.Protocol, Uri } { |
| | 1598 | const protocol = try uriProtocol(uri); |
| 1580 | var valid_uri = uri; | 1599 | var valid_uri = uri; |
| 1581 | // The host is always going to be needed as a raw string for hostname resolution anyway. | 1600 | // The host is always going to be needed as a raw string for hostname resolution anyway. |
| 1582 | valid_uri.host = .{ | 1601 | valid_uri.host = .{ |
| 1583 | .raw = try (uri.host orelse return error.UriMissingHost).toRawMaybeAlloc(arena), | 1602 | .raw = try (uri.host orelse return error.UriMissingHost).toRawMaybeAlloc(arena), |
| 1584 | }; | 1603 | }; |
| | 1604 | valid_uri.port = uri.port orelse protocol.port(); |
| 1585 | return .{ protocol, valid_uri }; | 1605 | return .{ protocol, valid_uri }; |
| 1586 | } | 1606 | } |
| 1587 | | 1607 | |
| 1588 | fn uriPort(uri: Uri, protocol: Connection.Protocol) u16 { | | |
| 1589 | return uri.port orelse switch (protocol) { | | |
| 1590 | .plain => 80, | | |
| 1591 | .tls => 443, | | |
| 1592 | }; | | |
| 1593 | } | | |
| 1594 | | | |
| 1595 | /// Open a connection to the host specified by `uri` and prepare to send a HTTP request. | 1608 | /// Open a connection to the host specified by `uri` and prepare to send a HTTP request. |
| 1596 | /// | 1609 | /// |
| 1597 | /// `uri` must remain alive during the entire request. | 1610 | /// `uri` must remain alive during the entire request. |
| ... | @@ -1637,7 +1650,7 @@ pub fn open( | ... | @@ -1637,7 +1650,7 @@ pub fn open( |
| 1637 | } | 1650 | } |
| 1638 | | 1651 | |
| 1639 | const conn = options.connection orelse | 1652 | const conn = options.connection orelse |
| 1640 | try client.connect(valid_uri.host.?.raw, uriPort(valid_uri, protocol), protocol); | 1653 | try client.connect(valid_uri.host.?.raw, valid_uri.port.?, protocol); |
| 1641 | | 1654 | |
| 1642 | var req: Request = .{ | 1655 | var req: Request = .{ |
| 1643 | .uri = valid_uri, | 1656 | .uri = valid_uri, |