Skip to content

Commit aea3426

Browse files
committed
basic/bearer testing
1 parent 4560f31 commit aea3426

File tree

3 files changed

+65
-5
lines changed

3 files changed

+65
-5
lines changed

src/http/client.zig

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,15 @@ pub const ProxyAuth = union(enum) {
5959
var encoder = std.base64.standard.Encoder;
6060
const size = encoder.calcSize(auth.user_pass.len);
6161
var buffer = try allocator.alloc(u8, size + prefix.len);
62-
std.mem.copyForwards(u8, buffer, prefix);
62+
@memcpy(buffer[0..prefix.len], prefix);
6363
_ = std.base64.standard.Encoder.encode(buffer[prefix.len..], auth.user_pass);
6464
return buffer;
6565
},
6666
.bearer => |*auth| {
6767
const prefix = "Bearer ";
6868
var buffer = try allocator.alloc(u8, auth.token.len + prefix.len);
69-
std.mem.copyForwards(u8, buffer, prefix);
70-
std.mem.copyForwards(u8, buffer[prefix.len..], auth.token);
69+
@memcpy(buffer[0..prefix.len], prefix);
70+
@memcpy(buffer[prefix.len..], auth.token);
7171
return buffer;
7272
},
7373
}
@@ -3078,15 +3078,56 @@ test "HttpClient: sync with body proxy CONNECT" {
30783078
}
30793079
try testing.expectEqual("over 9000!", try res.next());
30803080
try testing.expectEqual(201, res.header.status);
3081-
try testing.expectEqual(5, res.header.count());
3081+
try testing.expectEqual(6, res.header.count());
30823082
try testing.expectEqual("Close", res.header.get("connection"));
30833083
try testing.expectEqual("10", res.header.get("content-length"));
30843084
try testing.expectEqual("127.0.0.1", res.header.get("_host"));
30853085
try testing.expectEqual("Lightpanda/1.0", res.header.get("_user-agent"));
30863086
try testing.expectEqual("*/*", res.header.get("_accept"));
3087+
// Proxy headers
3088+
try testing.expectEqual("127.0.0.1:9582", res.header.get("__host"));
30873089
}
30883090
}
30893091

3092+
test "HttpClient: basic authentication CONNECT" {
3093+
const proxy_uri = try Uri.parse("http://127.0.0.1:9582/");
3094+
var client = try testClient(.{ .proxy_type = .connect, .http_proxy = proxy_uri, .proxy_auth = .{ .basic = .{ .user_pass = "user:pass" } } });
3095+
defer client.deinit();
3096+
3097+
const uri = try Uri.parse("http://127.0.0.1:9582/http_client/echo");
3098+
var req = try client.request(.GET, &uri);
3099+
defer req.deinit();
3100+
3101+
var res = try req.sendSync(.{});
3102+
3103+
try testing.expectEqual(201, res.header.status);
3104+
// Destination headers
3105+
try testing.expectEqual(null, res.header.get("_authorization"));
3106+
try testing.expectEqual(null, res.header.get("_proxy-authorization"));
3107+
// Proxy headers
3108+
try testing.expectEqual(null, res.header.get("__authorization"));
3109+
try testing.expectEqual("Basic dXNlcjpwYXNz", res.header.get("__proxy-authorization"));
3110+
}
3111+
test "HttpClient: bearer authentication CONNECT" {
3112+
const proxy_uri = try Uri.parse("http://127.0.0.1:9582/");
3113+
var client = try testClient(.{ .proxy_type = .connect, .http_proxy = proxy_uri, .proxy_auth = .{ .bearer = .{ .token = "fruitsalad" } } });
3114+
defer client.deinit();
3115+
3116+
const uri = try Uri.parse("http://127.0.0.1:9582/http_client/echo");
3117+
var req = try client.request(.GET, &uri);
3118+
defer req.deinit();
3119+
3120+
var res = try req.sendSync(.{});
3121+
3122+
try testing.expectEqual(201, res.header.status);
3123+
// Destination headers
3124+
try testing.expectEqual(null, res.header.get("_authorization"));
3125+
try testing.expectEqual(null, res.header.get("_proxy-authorization"));
3126+
// Proxy headers
3127+
try testing.expectEqual(null, res.header.get("__authorization"));
3128+
try testing.expectEqual("Bearer fruitsalad", res.header.get("__proxy-authorization"));
3129+
}
3130+
30903131
test "HttpClient: sync with gzip body" {
30913132
for (0..2) |i| {
30923133
var client = try testClient(.{});

src/main.zig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,7 @@ fn serveHTTP(address: std.net.Address) !void {
648648
var conn = try listener.accept();
649649
defer conn.stream.close();
650650
var http_server = std.http.Server.init(conn, &read_buffer);
651+
var connect_headers: std.ArrayListUnmanaged(std.http.Header) = .{};
651652
REQUEST: while (true) {
652653
var request = http_server.receiveHead() catch |err| switch (err) {
653654
error.HttpConnectionClosing => continue :ACCEPT,
@@ -659,6 +660,16 @@ fn serveHTTP(address: std.net.Address) !void {
659660

660661
if (request.head.method == .CONNECT) {
661662
try request.respond("", .{ .status = .ok });
663+
664+
// Proxy headers and destination headers are separated in the case of a CONNECT proxy
665+
// We store the CONNECT headers, then continue with the request for the destination
666+
var it = request.iterateHeaders();
667+
while (it.next()) |hdr| {
668+
try connect_headers.append(aa, .{
669+
.name = try std.fmt.allocPrint(aa, "__{s}", .{hdr.name}),
670+
.value = try aa.dupe(u8, hdr.value),
671+
});
672+
}
662673
continue :REQUEST;
663674
}
664675

@@ -699,6 +710,11 @@ fn serveHTTP(address: std.net.Address) !void {
699710
.value = hdr.value,
700711
});
701712
}
713+
714+
if (connect_headers.items.len > 0) {
715+
try headers.appendSlice(aa, connect_headers.items);
716+
connect_headers.clearRetainingCapacity();
717+
}
702718
try headers.append(aa, .{ .name = "Connection", .value = "Close" });
703719

704720
try request.respond("over 9000!", .{

src/testing.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ pub fn expectEqual(expected: anytype, actual: anytype) !void {
6666
if (@typeInfo(@TypeOf(expected)) == .null) {
6767
return std.testing.expectEqual(null, actual);
6868
}
69-
return expectEqual(expected, actual.?);
69+
if (actual) |_actual| {
70+
return expectEqual(expected, _actual);
71+
}
72+
return std.testing.expectEqual(expected, null);
7073
},
7174
.@"union" => |union_info| {
7275
if (union_info.tag_type == null) {

0 commit comments

Comments
 (0)