authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-01-30 14:06:53+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-01-31 12:05:12+01:00
log82b37ea0240c0e77857149d80beb4dda2b095dbb
treec4e2f561f9d80480f08fce2328f501e2f222b8e0
parentd7a27bf803fd29c499090c7bd0460fae9f0cf0f7

http: support basic access authentication


1 files changed, 34 insertions(+), 24 deletions(-)

lib/std/http/Client.zig+34-24
...@@ -657,7 +657,7 @@ pub const Request = struct {...@@ -657,7 +657,7 @@ pub const Request = struct {
657 };657 };
658 }658 }
659659
660 pub const SendError = Connection.WriteError || error{ InvalidContentLength, UnsupportedTransferEncoding };660 pub const SendError = Allocator.Error || Connection.WriteError || error{ InvalidContentLength, UnsupportedTransferEncoding };
661661
662 pub const SendOptions = struct {662 pub const SendOptions = struct {
663 /// Specifies that the uri should be used as is. You guarantee that the uri is already escaped.663 /// Specifies that the uri should be used as is. You guarantee that the uri is already escaped.
...@@ -695,6 +695,14 @@ pub const Request = struct {...@@ -695,6 +695,14 @@ pub const Request = struct {
695 try w.writeAll("\r\n");695 try w.writeAll("\r\n");
696 }696 }
697697
698 if ((req.uri.user != null or req.uri.password != null) and
699 !req.headers.contains("authorization"))
700 {
701 try w.writeAll("Authorization: ");
702 try w.writeAll(try basicAuthorizationValue(req.arena.allocator(), req.uri));
703 try w.writeAll("\r\n");
704 }
705
698 if (!req.headers.contains("user-agent")) {706 if (!req.headers.contains("user-agent")) {
699 try w.writeAll("User-Agent: zig/");707 try w.writeAll("User-Agent: zig/");
700 try w.writeAll(builtin.zig_version_string);708 try w.writeAll(builtin.zig_version_string);
...@@ -1122,19 +1130,11 @@ pub fn loadDefaultProxies(client: *Client) !void {...@@ -1122,19 +1130,11 @@ pub fn loadDefaultProxies(client: *Client) !void {
1122 },1130 },
1123 };1131 };
11241132
1125 if (uri.user != null and uri.password != null) {1133 if (uri.user != null or uri.password != null) {
1126 const prefix = "Basic ";1134 const authorization = try basicAuthorizationValue(client.allocator, uri);
11271135 defer client.allocator.free(authorization);
1128 const unencoded = try std.fmt.allocPrint(client.allocator, "{s}:{s}", .{ uri.user.?, uri.password.? });
1129 defer client.allocator.free(unencoded);
11301136
1131 const buffer = try client.allocator.alloc(u8, std.base64.standard.Encoder.calcSize(unencoded.len) + prefix.len);1137 try client.http_proxy.?.headers.append("proxy-authorization", authorization);
1132 defer client.allocator.free(buffer);
1133
1134 const result = std.base64.standard.Encoder.encode(buffer[prefix.len..], unencoded);
1135 @memcpy(buffer[0..prefix.len], prefix);
1136
1137 try client.http_proxy.?.headers.append("proxy-authorization", result);
1138 }1138 }
1139 }1139 }
11401140
...@@ -1173,21 +1173,31 @@ pub fn loadDefaultProxies(client: *Client) !void {...@@ -1173,21 +1173,31 @@ pub fn loadDefaultProxies(client: *Client) !void {
1173 },1173 },
1174 };1174 };
11751175
1176 if (uri.user != null and uri.password != null) {1176 if (uri.user != null or uri.password != null) {
1177 const prefix = "Basic ";1177 const authorization = try basicAuthorizationValue(client.allocator, uri);
1178 defer client.allocator.free(authorization);
11781179
1179 const unencoded = try std.fmt.allocPrint(client.allocator, "{s}:{s}", .{ uri.user.?, uri.password.? });1180 try client.https_proxy.?.headers.append("proxy-authorization", authorization);
1180 defer client.allocator.free(unencoded);1181 }
1182 }
1183}
11811184
1182 const buffer = try client.allocator.alloc(u8, std.base64.standard.Encoder.calcSize(unencoded.len) + prefix.len);1185pub fn basicAuthorizationValue(
1183 defer client.allocator.free(buffer);1186 allocator: Allocator,
1187 uri: Uri,
1188) Allocator.Error![]const u8 {
1189 const prefix = "Basic ";
11841190
1185 const result = std.base64.standard.Encoder.encode(buffer[prefix.len..], unencoded);1191 const unencoded = try std.fmt.allocPrint(allocator, "{s}:{s}", .{ uri.user orelse "", uri.password orelse "" });
1186 @memcpy(buffer[0..prefix.len], prefix);1192 defer allocator.free(unencoded);
11871193
1188 try client.https_proxy.?.headers.append("proxy-authorization", result);1194 const buffer = try allocator.alloc(u8, prefix.len + std.base64.standard.Encoder.calcSize(unencoded.len));
1189 }1195 errdefer allocator.free(buffer);
1190 }1196
1197 @memcpy(buffer[0..prefix.len], prefix);
1198 _ = std.base64.standard.Encoder.encode(buffer[prefix.len..], unencoded);
1199
1200 return buffer;
1191}1201}
11921202
1193pub const ConnectTcpError = Allocator.Error || error{ ConnectionRefused, NetworkUnreachable, ConnectionTimedOut, ConnectionResetByPeer, TemporaryNameServerFailure, NameServerFailure, UnknownHostName, HostLacksNetworkAddresses, UnexpectedConnectFailure, TlsInitializationFailed };1203pub const ConnectTcpError = Allocator.Error || error{ ConnectionRefused, NetworkUnreachable, ConnectionTimedOut, ConnectionResetByPeer, TemporaryNameServerFailure, NameServerFailure, UnknownHostName, HostLacksNetworkAddresses, UnexpectedConnectFailure, TlsInitializationFailed };