Compare commits
2 Commits
c1c40644ac
...
e5b662873a
Author | SHA1 | Date | |
---|---|---|---|
e5b662873a | |||
a9f99c0205 |
49
src/aws.zig
49
src/aws.zig
|
@ -1380,6 +1380,49 @@ const TestOptions = struct {
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
/// Builtin hashmap for strings as keys.
|
||||||
|
/// Key memory is managed by the caller. Keys and values
|
||||||
|
/// will not automatically be freed.
|
||||||
|
pub fn StringCaseInsensitiveHashMap(comptime V: type) type {
|
||||||
|
return std.HashMap([]const u8, V, StringInsensitiveContext, std.hash_map.default_max_load_percentage);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const StringInsensitiveContext = struct {
|
||||||
|
pub fn hash(self: @This(), s: []const u8) u64 {
|
||||||
|
_ = self;
|
||||||
|
return hashString(s);
|
||||||
|
}
|
||||||
|
pub fn eql(self: @This(), a: []const u8, b: []const u8) bool {
|
||||||
|
_ = self;
|
||||||
|
return eqlString(a, b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn eqlString(a: []const u8, b: []const u8) bool {
|
||||||
|
return std.ascii.eqlIgnoreCase(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hashString(s: []const u8) u64 {
|
||||||
|
var buf: [1024]u8 = undefined;
|
||||||
|
if (s.len > buf.len) unreachable; // tolower has a debug assert, but we want non-debug check too
|
||||||
|
const lower_s = std.ascii.lowerString(buf[0..], s);
|
||||||
|
return std.hash.Wyhash.hash(0, lower_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expectNoDuplicateHeaders(self: *Self) !void {
|
||||||
|
// As header keys are
|
||||||
|
var hm = StringCaseInsensitiveHashMap(void).init(self.allocator);
|
||||||
|
try hm.ensureTotalCapacity(@intCast(self.request_headers.len));
|
||||||
|
defer hm.deinit();
|
||||||
|
for (self.request_headers) |h| {
|
||||||
|
if (hm.getKey(h.name)) |_| {
|
||||||
|
log.err("Duplicate key detected. Key name: {s}", .{h.name});
|
||||||
|
return error.duplicateKeyDetected;
|
||||||
|
}
|
||||||
|
try hm.put(h.name, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn expectHeader(self: *Self, name: []const u8, value: []const u8) !void {
|
fn expectHeader(self: *Self, name: []const u8, value: []const u8) !void {
|
||||||
for (self.request_headers) |h|
|
for (self.request_headers) |h|
|
||||||
if (std.ascii.eqlIgnoreCase(name, h.name) and
|
if (std.ascii.eqlIgnoreCase(name, h.name) and
|
||||||
|
@ -1992,6 +2035,9 @@ test "rest_xml_anything_but_s3: CloudFront list key groups" {
|
||||||
try std.testing.expectEqual(@as(i64, 100), call.response.key_group_list.?.max_items);
|
try std.testing.expectEqual(@as(i64, 100), call.response.key_group_list.?.max_items);
|
||||||
}
|
}
|
||||||
test "rest_xml_with_input: S3 put object" {
|
test "rest_xml_with_input: S3 put object" {
|
||||||
|
// const old = std.testing.log_level;
|
||||||
|
// defer std.testing.log_level = old;
|
||||||
|
// std.testing.log_level = .debug;
|
||||||
const allocator = std.testing.allocator;
|
const allocator = std.testing.allocator;
|
||||||
var test_harness = TestSetup.init(.{
|
var test_harness = TestSetup.init(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
|
@ -2018,13 +2064,14 @@ test "rest_xml_with_input: S3 put object" {
|
||||||
.body = "bar",
|
.body = "bar",
|
||||||
.storage_class = "STANDARD",
|
.storage_class = "STANDARD",
|
||||||
}, s3opts);
|
}, s3opts);
|
||||||
|
defer result.deinit();
|
||||||
for (test_harness.request_options.request_headers) |header| {
|
for (test_harness.request_options.request_headers) |header| {
|
||||||
std.log.info("Request header: {s}: {s}", .{ header.name, header.value });
|
std.log.info("Request header: {s}: {s}", .{ header.name, header.value });
|
||||||
}
|
}
|
||||||
|
try test_harness.request_options.expectNoDuplicateHeaders();
|
||||||
std.log.info("PutObject Request id: {s}", .{result.response_metadata.request_id});
|
std.log.info("PutObject Request id: {s}", .{result.response_metadata.request_id});
|
||||||
std.log.info("PutObject etag: {s}", .{result.response.e_tag.?});
|
std.log.info("PutObject etag: {s}", .{result.response.e_tag.?});
|
||||||
//mysfitszj3t6webstack-hostingbucketa91a61fe-1ep3ezkgwpxr0.s3.us-west-2.amazonaws.com
|
//mysfitszj3t6webstack-hostingbucketa91a61fe-1ep3ezkgwpxr0.s3.us-west-2.amazonaws.com
|
||||||
defer result.deinit();
|
|
||||||
test_harness.stop();
|
test_harness.stop();
|
||||||
// Request expectations
|
// Request expectations
|
||||||
try std.testing.expectEqual(std.http.Method.PUT, test_harness.request_options.request_method);
|
try std.testing.expectEqual(std.http.Method.PUT, test_harness.request_options.request_method);
|
||||||
|
|
|
@ -190,6 +190,16 @@ pub const AwsHttp = struct {
|
||||||
.response_storage = .{ .dynamic = &resp_payload },
|
.response_storage = .{ .dynamic = &resp_payload },
|
||||||
.raw_uri = true,
|
.raw_uri = true,
|
||||||
.location = .{ .url = url },
|
.location = .{ .url = url },
|
||||||
|
// we need full control over most headers. I wish libraries would do a
|
||||||
|
// better job of having default headers as an opt-in...
|
||||||
|
.headers = .{
|
||||||
|
.host = .omit,
|
||||||
|
.authorization = .omit,
|
||||||
|
.user_agent = .omit,
|
||||||
|
.connection = .default, // we can let the client manage this...it has no impact to us
|
||||||
|
.accept_encoding = .default, // accept encoding (gzip, deflate) *should* be ok
|
||||||
|
.content_type = .omit,
|
||||||
|
},
|
||||||
.extra_headers = headers.items,
|
.extra_headers = headers.items,
|
||||||
});
|
});
|
||||||
// TODO: Need to test for payloads > 2^14. I believe one of our tests does this, but not sure
|
// TODO: Need to test for payloads > 2^14. I believe one of our tests does this, but not sure
|
||||||
|
|
Loading…
Reference in New Issue
Block a user