Commit c1e7d0c08f
Changed files (2)
lib
std
lib/std/http/Client.zig
@@ -1141,8 +1141,10 @@ pub fn loadDefaultProxies(client: *Client) !void {
};
if (uri.user != null or uri.password != null) {
- var authorization: [basic_authorization.max_value_len]u8 = undefined;
- try client.http_proxy.?.headers.append("proxy-authorization", basic_authorization.value(uri, &authorization));
+ const authorization = try client.allocator.alloc(u8, basic_authorization.valueLengthFromUri(uri));
+ errdefer client.allocator.free(authorization);
+ std.debug.assert(basic_authorization.value(uri, authorization).len == authorization.len);
+ try client.http_proxy.?.headers.appendOwned(.{ .unowned = "proxy-authorization" }, .{ .owned = authorization });
}
}
@@ -1182,8 +1184,10 @@ pub fn loadDefaultProxies(client: *Client) !void {
};
if (uri.user != null or uri.password != null) {
- var authorization: [basic_authorization.max_value_len]u8 = undefined;
- try client.https_proxy.?.headers.append("proxy-authorization", basic_authorization.value(uri, &authorization));
+ const authorization = try client.allocator.alloc(u8, basic_authorization.valueLengthFromUri(uri));
+ errdefer client.allocator.free(authorization);
+ std.debug.assert(basic_authorization.value(uri, authorization).len == authorization.len);
+ try client.https_proxy.?.headers.appendOwned(.{ .unowned = "proxy-authorization" }, .{ .owned = authorization });
}
}
}
lib/std/http/Headers.zig
@@ -91,30 +91,64 @@ pub const Headers = struct {
///
/// If the `owned` field is true, both name and value will be copied.
pub fn append(headers: *Headers, name: []const u8, value: []const u8) !void {
- const n = headers.list.items.len;
+ try headers.appendOwned(.{ .unowned = name }, .{ .unowned = value });
+ }
- const value_duped = if (headers.owned) try headers.allocator.dupe(u8, value) else value;
- errdefer if (headers.owned) headers.allocator.free(value_duped);
+ pub const OwnedString = union(enum) {
+ /// A string allocated by the `allocator` field.
+ owned: []u8,
+ /// A string to be copied by the `allocator` field.
+ unowned: []const u8,
+ };
- var entry = Field{ .name = undefined, .value = value_duped };
+ /// Appends a header to the list.
+ ///
+ /// If the `owned` field is true, `name` and `value` will be copied if unowned.
+ pub fn appendOwned(headers: *Headers, name: OwnedString, value: OwnedString) !void {
+ const n = headers.list.items.len;
+ try headers.list.ensureUnusedCapacity(headers.allocator, 1);
+
+ const owned_value = switch (value) {
+ .owned => |owned| owned,
+ .unowned => |unowned| if (headers.owned)
+ try headers.allocator.dupe(u8, unowned)
+ else
+ unowned,
+ };
+ errdefer if (value == .unowned and headers.owned) headers.allocator.free(owned_value);
+
+ var entry = Field{ .name = undefined, .value = owned_value };
+
+ if (headers.index.getEntry(switch (name) {
+ inline else => |string| string,
+ })) |kv| {
+ defer switch (name) {
+ .owned => |owned| headers.allocator.free(owned),
+ .unowned => {},
+ };
- if (headers.index.getEntry(name)) |kv| {
entry.name = kv.key_ptr.*;
try kv.value_ptr.append(headers.allocator, n);
} else {
- const name_duped = if (headers.owned) try std.ascii.allocLowerString(headers.allocator, name) else name;
- errdefer if (headers.owned) headers.allocator.free(name_duped);
+ const owned_name = switch (name) {
+ .owned => |owned| owned,
+ .unowned => |unowned| if (headers.owned)
+ try std.ascii.allocLowerString(headers.allocator, unowned)
+ else
+ unowned,
+ };
+ errdefer if (name == .unowned and headers.owned) headers.allocator.free(owned_name);
- entry.name = name_duped;
+ entry.name = owned_name;
var new_index = try HeaderIndexList.initCapacity(headers.allocator, 1);
errdefer new_index.deinit(headers.allocator);
new_index.appendAssumeCapacity(n);
- try headers.index.put(headers.allocator, name_duped, new_index);
+ try headers.index.put(headers.allocator, owned_name, new_index);
}
- try headers.list.append(headers.allocator, entry);
+ headers.list.appendAssumeCapacity(entry);
}
/// Returns true if this list of headers contains the given name.