2021-04-27 18:24:01 +00:00
|
|
|
const std = @import("std");
|
|
|
|
const aws = @import("aws.zig");
|
2021-05-13 22:53:53 +00:00
|
|
|
const json = @import("json.zig");
|
2021-04-27 18:24:01 +00:00
|
|
|
|
2022-01-20 03:29:58 +00:00
|
|
|
var verbose: u8 = 0;
|
2021-06-24 01:23:07 +00:00
|
|
|
|
2021-04-27 18:24:01 +00:00
|
|
|
pub fn log(
|
|
|
|
comptime level: std.log.Level,
|
|
|
|
comptime scope: @TypeOf(.EnumLiteral),
|
|
|
|
comptime format: []const u8,
|
|
|
|
args: anytype,
|
|
|
|
) void {
|
2022-01-20 03:29:58 +00:00
|
|
|
// Ignore aws_signing messages
|
2023-08-04 17:07:58 +00:00
|
|
|
if (verbose < 3 and scope == .aws_signing and @intFromEnum(level) >= @intFromEnum(std.log.Level.debug))
|
2022-01-20 03:29:58 +00:00
|
|
|
return;
|
2022-02-16 22:14:54 +00:00
|
|
|
// Ignore aws_credentials messages
|
2023-08-04 17:07:58 +00:00
|
|
|
if (verbose < 3 and scope == .aws_credentials and @intFromEnum(level) >= @intFromEnum(std.log.Level.debug))
|
2022-02-16 22:14:54 +00:00
|
|
|
return;
|
|
|
|
// Ignore xml_shaper messages
|
2023-08-04 17:07:58 +00:00
|
|
|
if (verbose < 3 and scope == .xml_shaper and @intFromEnum(level) >= @intFromEnum(std.log.Level.debug))
|
2022-02-16 22:14:54 +00:00
|
|
|
return;
|
|
|
|
// Ignore date messages
|
2023-08-04 17:07:58 +00:00
|
|
|
if (verbose < 3 and scope == .date and @intFromEnum(level) >= @intFromEnum(std.log.Level.debug))
|
2022-02-16 22:14:54 +00:00
|
|
|
return;
|
2021-04-27 18:24:01 +00:00
|
|
|
// Ignore awshttp messages
|
2023-08-04 17:07:58 +00:00
|
|
|
if (verbose < 2 and scope == .awshttp and @intFromEnum(level) >= @intFromEnum(std.log.Level.debug))
|
2022-06-06 01:23:16 +00:00
|
|
|
return;
|
|
|
|
|
2023-08-04 17:07:58 +00:00
|
|
|
if (verbose < 1 and scope == .aws and @intFromEnum(level) >= @intFromEnum(std.log.Level.debug))
|
2021-04-27 18:24:01 +00:00
|
|
|
return;
|
|
|
|
const scope_prefix = "(" ++ @tagName(scope) ++ "): ";
|
|
|
|
const prefix = "[" ++ @tagName(level) ++ "] " ++ scope_prefix;
|
|
|
|
|
|
|
|
// Print the message to stderr, silently ignoring any errors
|
2021-12-23 16:51:48 +00:00
|
|
|
std.debug.getStderrMutex().lock();
|
|
|
|
defer std.debug.getStderrMutex().unlock();
|
2021-04-27 18:24:01 +00:00
|
|
|
const stderr = std.io.getStdErr().writer();
|
|
|
|
nosuspend stderr.print(prefix ++ format ++ "\n", args) catch return;
|
|
|
|
}
|
|
|
|
|
upgrade to nominated zig 2024.3.0-mach (0.12.0-dev.3180+83e578a18)
There were significant changes to the way HTTP operates since 0.11,
effecting client operations, but more substantially, the server
implementation, which effected the test harness.
std.http.Headers was removed, including the getFirstValue function, which
needed to be replicated. On the plus side, a std.http.Header struct was
added, identical to our own structure, so I have removed out own header
in favor of stdlib.
On the Http client side, I have switched to use the fetch API. Proxy
support is built in, but we are using (mostly) our own implementation
for now, with the remaining conversion left as a TODO item. Raw URIs are
now supported, so the workaround for issue 17015 has been removed. Large
payloads should also be fixed, but this has not been tested.
The standard library now adds the content-length header
(unconditionally), which is a decision of dubious nature. I have removed
the addition of content-length, which also means it is not present
during signing. This should be allowed.
Dependency loop on fieldTransformer was fixed. This should have been
a problem on zig 0.11, but was not. This effected the API for the json
parsing, but we were not using that. At the call site, these did not
need to be specified as references.
With the http server no longer doing all the allocations it once was,
the test harness now has a lot more allocations to perform. To alleviate
the bookeeping, this was moved to an Arena allocator. The client,
which is really what is under test, continues to use the allocator
passed.
2024-04-02 16:13:45 +00:00
|
|
|
pub const std_options = std.Options{
|
|
|
|
.logFn = log,
|
2023-08-29 18:29:16 +00:00
|
|
|
};
|
2021-06-24 01:23:07 +00:00
|
|
|
const Tests = enum {
|
|
|
|
query_no_input,
|
|
|
|
query_with_input,
|
|
|
|
ec2_query_no_input,
|
2022-05-25 18:38:34 +00:00
|
|
|
ec2_query_with_input,
|
2021-08-12 21:24:24 +00:00
|
|
|
json_1_0_query_with_input,
|
|
|
|
json_1_0_query_no_input,
|
2021-08-13 00:51:47 +00:00
|
|
|
json_1_1_query_with_input,
|
|
|
|
json_1_1_query_no_input,
|
2021-08-14 01:12:05 +00:00
|
|
|
rest_json_1_query_no_input,
|
|
|
|
rest_json_1_query_with_input,
|
2021-08-25 00:02:28 +00:00
|
|
|
rest_json_1_work_with_lambda,
|
2022-05-25 22:27:13 +00:00
|
|
|
rest_xml_no_input,
|
2022-05-29 03:14:42 +00:00
|
|
|
rest_xml_anything_but_s3,
|
2022-06-06 01:34:39 +00:00
|
|
|
rest_xml_work_with_s3,
|
2021-06-24 01:23:07 +00:00
|
|
|
};
|
2021-05-13 22:53:53 +00:00
|
|
|
|
2021-06-24 01:23:07 +00:00
|
|
|
pub fn main() anyerror!void {
|
2022-01-12 17:18:16 +00:00
|
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
2021-06-24 01:23:07 +00:00
|
|
|
defer _ = gpa.deinit();
|
2021-12-23 16:51:48 +00:00
|
|
|
const allocator = gpa.allocator();
|
2021-06-24 01:23:07 +00:00
|
|
|
var tests = std.ArrayList(Tests).init(allocator);
|
|
|
|
defer tests.deinit();
|
2023-08-15 15:50:22 +00:00
|
|
|
var args = try std.process.argsWithAllocator(allocator);
|
|
|
|
defer args.deinit();
|
2023-08-29 14:26:11 +00:00
|
|
|
const stdout_raw = std.io.getStdOut().writer();
|
|
|
|
var bw = std.io.bufferedWriter(stdout_raw);
|
|
|
|
defer bw.flush() catch unreachable;
|
|
|
|
const stdout = bw.writer();
|
|
|
|
var arg0: ?[]const u8 = null;
|
upgrade to nominated zig 2024.3.0-mach (0.12.0-dev.3180+83e578a18)
There were significant changes to the way HTTP operates since 0.11,
effecting client operations, but more substantially, the server
implementation, which effected the test harness.
std.http.Headers was removed, including the getFirstValue function, which
needed to be replicated. On the plus side, a std.http.Header struct was
added, identical to our own structure, so I have removed out own header
in favor of stdlib.
On the Http client side, I have switched to use the fetch API. Proxy
support is built in, but we are using (mostly) our own implementation
for now, with the remaining conversion left as a TODO item. Raw URIs are
now supported, so the workaround for issue 17015 has been removed. Large
payloads should also be fixed, but this has not been tested.
The standard library now adds the content-length header
(unconditionally), which is a decision of dubious nature. I have removed
the addition of content-length, which also means it is not present
during signing. This should be allowed.
Dependency loop on fieldTransformer was fixed. This should have been
a problem on zig 0.11, but was not. This effected the API for the json
parsing, but we were not using that. At the call site, these did not
need to be specified as references.
With the http server no longer doing all the allocations it once was,
the test harness now has a lot more allocations to perform. To alleviate
the bookeeping, this was moved to an Arena allocator. The client,
which is really what is under test, continues to use the allocator
passed.
2024-04-02 16:13:45 +00:00
|
|
|
var proxy: ?std.http.Client.Proxy = null;
|
2023-08-04 17:06:54 +00:00
|
|
|
while (args.next()) |arg| {
|
2023-08-29 14:26:11 +00:00
|
|
|
if (arg0 == null) arg0 = arg;
|
|
|
|
if (std.mem.eql(u8, "-h", arg) or std.mem.eql(u8, "--help", arg)) {
|
|
|
|
try stdout.print(
|
2023-08-29 18:24:34 +00:00
|
|
|
\\usage: {?s} [-h|--help] [-v][-v][-v] [-x|--proxy <proxy url>] [tests...]
|
2023-08-29 14:26:11 +00:00
|
|
|
\\
|
|
|
|
\\Where tests are one of the following:
|
|
|
|
\\
|
|
|
|
, .{arg0});
|
|
|
|
inline for (std.meta.fields(Tests)) |enumfield| {
|
|
|
|
try stdout.print("* {s}\n", .{enumfield.name});
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2023-08-29 18:24:34 +00:00
|
|
|
if (std.mem.eql(u8, "-x", arg) or std.mem.eql(u8, "--proxy", arg)) {
|
|
|
|
proxy = try proxyFromString(args.next().?); // parse stuff
|
|
|
|
continue;
|
|
|
|
}
|
2023-08-29 22:21:15 +00:00
|
|
|
if (std.mem.startsWith(u8, arg, "-v")) {
|
|
|
|
for (arg[1..]) |c| {
|
|
|
|
if (c != 'v') return error.InvalidArgument;
|
|
|
|
verbose += 1;
|
|
|
|
}
|
2021-06-24 01:23:07 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
inline for (@typeInfo(Tests).Enum.fields) |f| {
|
|
|
|
if (std.mem.eql(u8, f.name, arg)) {
|
|
|
|
try tests.append(@field(Tests, f.name));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tests.items.len == 0) {
|
|
|
|
inline for (@typeInfo(Tests).Enum.fields) |f|
|
|
|
|
try tests.append(@field(Tests, f.name));
|
|
|
|
}
|
2021-04-27 18:24:01 +00:00
|
|
|
|
2021-08-25 00:02:28 +00:00
|
|
|
std.log.info("Start\n", .{});
|
2023-08-29 18:24:34 +00:00
|
|
|
const client_options = aws.ClientOptions{ .proxy = proxy };
|
|
|
|
var client = aws.Client.init(allocator, client_options);
|
2021-04-27 18:24:01 +00:00
|
|
|
const options = aws.Options{
|
|
|
|
.region = "us-west-2",
|
2021-08-25 00:02:28 +00:00
|
|
|
.client = client,
|
2021-04-27 18:24:01 +00:00
|
|
|
};
|
|
|
|
defer client.deinit();
|
|
|
|
|
2023-08-28 23:42:43 +00:00
|
|
|
// As of 2023-08-28, only ECS from this list supports TLS v1.3
|
|
|
|
// AWS commitment is to enable all services by 2023-12-31
|
2022-05-29 03:14:42 +00:00
|
|
|
const services = aws.Services(.{ .sts, .ec2, .dynamo_db, .ecs, .lambda, .sqs, .s3, .cloudfront }){};
|
2021-04-27 18:24:01 +00:00
|
|
|
|
2021-06-24 01:23:07 +00:00
|
|
|
for (tests.items) |t| {
|
|
|
|
std.log.info("===== Start Test: {s} =====", .{@tagName(t)});
|
|
|
|
switch (t) {
|
|
|
|
.query_no_input => {
|
2021-08-25 00:02:28 +00:00
|
|
|
const call = try aws.Request(services.sts.get_caller_identity).call(.{}, options);
|
|
|
|
// const call = try client.call(services.sts.get_caller_identity.Request{}, options);
|
2021-08-14 01:12:05 +00:00
|
|
|
defer call.deinit();
|
2023-08-29 18:29:50 +00:00
|
|
|
std.log.info("arn: {s}", .{call.response.arn.?});
|
|
|
|
std.log.info("id: {s}", .{call.response.user_id.?});
|
|
|
|
std.log.info("account: {s}", .{call.response.account.?});
|
|
|
|
std.log.info("requestId: {s}", .{call.response_metadata.request_id});
|
2021-06-24 01:23:07 +00:00
|
|
|
},
|
|
|
|
.query_with_input => {
|
2022-01-21 14:15:48 +00:00
|
|
|
const call = try client.call(services.sqs.list_queues.Request{
|
|
|
|
.queue_name_prefix = "s",
|
2021-06-24 01:23:07 +00:00
|
|
|
}, options);
|
2021-08-14 01:12:05 +00:00
|
|
|
defer call.deinit();
|
2023-08-29 18:29:50 +00:00
|
|
|
std.log.info("request id: {s}", .{call.response_metadata.request_id});
|
2023-08-14 17:06:28 +00:00
|
|
|
std.log.info("account has queues with prefix 's': {}", .{call.response.queue_urls != null});
|
2021-08-12 21:24:24 +00:00
|
|
|
},
|
|
|
|
.json_1_0_query_with_input => {
|
2021-08-14 01:12:05 +00:00
|
|
|
const call = try client.call(services.dynamo_db.list_tables.Request{
|
2021-08-12 21:24:24 +00:00
|
|
|
.limit = 1,
|
|
|
|
}, options);
|
2021-08-14 01:12:05 +00:00
|
|
|
defer call.deinit();
|
2023-08-29 18:29:50 +00:00
|
|
|
std.log.info("request id: {s}", .{call.response_metadata.request_id});
|
2023-08-14 17:06:28 +00:00
|
|
|
std.log.info("account has tables: {}", .{call.response.table_names.?.len > 0});
|
2021-08-12 21:24:24 +00:00
|
|
|
},
|
|
|
|
.json_1_0_query_no_input => {
|
2021-08-14 01:12:05 +00:00
|
|
|
const call = try client.call(services.dynamo_db.describe_limits.Request{}, options);
|
|
|
|
defer call.deinit();
|
2023-08-14 17:06:28 +00:00
|
|
|
std.log.info("account read capacity limit: {?d}", .{call.response.account_max_read_capacity_units});
|
2021-06-24 01:23:07 +00:00
|
|
|
},
|
2021-08-13 00:51:47 +00:00
|
|
|
.json_1_1_query_with_input => {
|
2021-08-14 01:12:05 +00:00
|
|
|
const call = try client.call(services.ecs.list_clusters.Request{
|
2021-08-13 00:51:47 +00:00
|
|
|
.max_results = 1,
|
|
|
|
}, options);
|
2021-08-14 01:12:05 +00:00
|
|
|
defer call.deinit();
|
2023-08-29 18:29:50 +00:00
|
|
|
std.log.info("request id: {s}", .{call.response_metadata.request_id});
|
2023-08-14 17:06:28 +00:00
|
|
|
std.log.info("account has clusters: {}", .{call.response.cluster_arns.?.len > 0});
|
2021-08-13 00:51:47 +00:00
|
|
|
},
|
|
|
|
.json_1_1_query_no_input => {
|
2021-08-14 01:12:05 +00:00
|
|
|
const call = try client.call(services.ecs.list_clusters.Request{}, options);
|
|
|
|
defer call.deinit();
|
2023-08-29 18:29:50 +00:00
|
|
|
std.log.info("request id: {s}", .{call.response_metadata.request_id});
|
2023-08-14 17:06:28 +00:00
|
|
|
std.log.info("account has clusters: {}", .{call.response.cluster_arns.?.len > 0});
|
2021-08-14 01:12:05 +00:00
|
|
|
},
|
|
|
|
.rest_json_1_query_with_input => {
|
|
|
|
const call = try client.call(services.lambda.list_functions.Request{
|
|
|
|
.max_items = 1,
|
|
|
|
}, options);
|
|
|
|
defer call.deinit();
|
2023-08-29 18:29:50 +00:00
|
|
|
std.log.info("request id: {s}", .{call.response_metadata.request_id});
|
2023-08-14 17:06:28 +00:00
|
|
|
std.log.info("account has functions: {}", .{call.response.functions.?.len > 0});
|
2021-08-14 01:12:05 +00:00
|
|
|
},
|
|
|
|
.rest_json_1_query_no_input => {
|
|
|
|
const call = try client.call(services.lambda.list_functions.Request{}, options);
|
|
|
|
defer call.deinit();
|
2023-08-29 18:29:50 +00:00
|
|
|
std.log.info("request id: {s}", .{call.response_metadata.request_id});
|
2023-08-14 17:06:28 +00:00
|
|
|
std.log.info("account has functions: {}", .{call.response.functions.?.len > 0});
|
2021-08-25 00:02:28 +00:00
|
|
|
},
|
|
|
|
.rest_json_1_work_with_lambda => {
|
2023-08-30 19:53:42 +00:00
|
|
|
const call = try client.call(services.lambda.list_functions.Request{}, options);
|
|
|
|
defer call.deinit();
|
|
|
|
std.log.info("list request id: {s}", .{call.response_metadata.request_id});
|
2023-08-30 20:49:29 +00:00
|
|
|
if (call.response.functions) |fns| {
|
|
|
|
if (fns.len > 0) {
|
|
|
|
const func = fns[0];
|
|
|
|
const arn = func.function_arn.?;
|
|
|
|
// This is a bit ugly. Maybe a helper function in the library would help?
|
|
|
|
var tags = try std.ArrayList(@typeInfo(try typeForField(services.lambda.tag_resource.Request, "tags")).Pointer.child).initCapacity(allocator, 1);
|
|
|
|
defer tags.deinit();
|
|
|
|
tags.appendAssumeCapacity(.{ .key = "Foo", .value = "Bar" });
|
|
|
|
const req = services.lambda.tag_resource.Request{ .resource = arn, .tags = tags.items };
|
|
|
|
const addtag = try aws.Request(services.lambda.tag_resource).call(req, options);
|
|
|
|
// TODO: This is failing due to double-encoding (see zig issue 17015)
|
|
|
|
defer addtag.deinit();
|
|
|
|
// const addtag = try client.call(services.lambda.tag_resource.Request{ .resource = arn, .tags = &.{.{ .key = "Foo", .value = "Bar" }} }, options);
|
|
|
|
std.log.info("add tag request id: {s}", .{addtag.response_metadata.request_id});
|
|
|
|
var keys = [_][]const u8{"Foo"}; // Would love to have a way to express this without burning a var here
|
|
|
|
const deletetag = try aws.Request(services.lambda.untag_resource).call(.{ .tag_keys = keys[0..], .resource = arn }, options);
|
|
|
|
defer deletetag.deinit();
|
|
|
|
std.log.info("delete tag request id: {s}", .{deletetag.response_metadata.request_id});
|
|
|
|
} else {
|
|
|
|
std.log.err("no functions to work with", .{});
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
std.log.err("no functions to work with", .{});
|
|
|
|
}
|
2021-08-13 00:51:47 +00:00
|
|
|
},
|
2021-06-24 01:23:07 +00:00
|
|
|
.ec2_query_no_input => {
|
2023-08-28 20:10:16 +00:00
|
|
|
// Describe regions is a simpler request and easier to debug
|
2023-08-28 00:04:49 +00:00
|
|
|
const result = try client.call(services.ec2.describe_regions.Request{}, options);
|
|
|
|
defer result.deinit();
|
2023-08-29 18:29:50 +00:00
|
|
|
std.log.info("request id: {s}", .{result.response_metadata.request_id});
|
2023-08-28 00:04:49 +00:00
|
|
|
std.log.info("region count: {d}", .{result.response.regions.?.len});
|
2022-05-25 18:38:34 +00:00
|
|
|
},
|
|
|
|
.ec2_query_with_input => {
|
2022-02-11 17:17:27 +00:00
|
|
|
// Describe instances is more interesting
|
2023-08-28 00:04:49 +00:00
|
|
|
const result = try client.call(services.ec2.describe_instances.Request{ .max_results = 6 }, options);
|
|
|
|
defer result.deinit();
|
|
|
|
std.log.info("reservation count: {d}", .{result.response.reservations.?.len});
|
|
|
|
var items: usize = 0;
|
|
|
|
for (result.response.reservations.?) |reservation| {
|
|
|
|
items += reservation.instances.?.len;
|
|
|
|
}
|
|
|
|
std.log.info("items count: {d}", .{items});
|
|
|
|
var next = result.response.next_token;
|
|
|
|
while (next) |next_token| {
|
|
|
|
std.log.info("more results available: fetching again", .{});
|
|
|
|
|
|
|
|
const more = try aws.Request(services.ec2.describe_instances)
|
|
|
|
.call(.{ .next_token = next_token, .max_results = 6 }, options);
|
|
|
|
defer more.deinit();
|
|
|
|
// we could have exactly 6, which means we have a next token(?!) but not
|
|
|
|
// any actual additional data
|
|
|
|
if (more.response.reservations == null) break;
|
|
|
|
std.log.info("reservation count: {d}", .{more.response.reservations.?.len});
|
|
|
|
var batch_items: usize = 0;
|
|
|
|
for (more.response.reservations.?) |reservation| {
|
|
|
|
batch_items += reservation.instances.?.len;
|
|
|
|
}
|
|
|
|
std.log.info("items count: {d}", .{batch_items});
|
|
|
|
items += batch_items;
|
|
|
|
std.log.info("total items count: {d}", .{items});
|
|
|
|
next = more.response.next_token;
|
|
|
|
}
|
2021-06-24 01:23:07 +00:00
|
|
|
},
|
2023-08-28 20:30:39 +00:00
|
|
|
// ^^ under test. vv still in progress
|
2022-05-25 22:27:13 +00:00
|
|
|
.rest_xml_no_input => {
|
|
|
|
const result = try client.call(services.s3.list_buckets.Request{}, options);
|
|
|
|
defer result.deinit();
|
2023-08-29 18:29:50 +00:00
|
|
|
std.log.info("request id: {s}", .{result.response_metadata.request_id});
|
2022-05-25 22:27:13 +00:00
|
|
|
std.log.info("bucket count: {d}", .{result.response.buckets.?.len});
|
|
|
|
},
|
2022-05-29 03:14:42 +00:00
|
|
|
.rest_xml_anything_but_s3 => {
|
|
|
|
const result = try client.call(services.cloudfront.list_key_groups.Request{}, options);
|
|
|
|
defer result.deinit();
|
2023-08-29 18:29:50 +00:00
|
|
|
std.log.info("request id: {s}", .{result.response_metadata.request_id});
|
2022-05-29 03:14:42 +00:00
|
|
|
const list = result.response.key_group_list.?;
|
2023-08-14 17:06:28 +00:00
|
|
|
std.log.info("key group list max: {?d}", .{list.max_items});
|
2022-05-29 03:14:42 +00:00
|
|
|
std.log.info("key group quantity: {d}", .{list.quantity});
|
|
|
|
},
|
2022-06-06 01:34:39 +00:00
|
|
|
.rest_xml_work_with_s3 => {
|
2022-06-29 16:24:16 +00:00
|
|
|
const key = "i/am/a/teapot/foo";
|
2023-08-27 18:54:31 +00:00
|
|
|
// // const key = "foo";
|
|
|
|
//
|
2022-06-06 01:34:39 +00:00
|
|
|
const bucket = blk: {
|
|
|
|
const result = try client.call(services.s3.list_buckets.Request{}, options);
|
|
|
|
defer result.deinit();
|
|
|
|
const bucket = result.response.buckets.?[result.response.buckets.?.len - 1];
|
2023-08-29 18:29:50 +00:00
|
|
|
std.log.info("ListBuckets request id: {s}", .{result.response_metadata.request_id});
|
2023-08-29 19:47:22 +00:00
|
|
|
std.log.info("bucket name: {s}", .{bucket.name.?});
|
2022-06-06 01:34:39 +00:00
|
|
|
break :blk try allocator.dupe(u8, bucket.name.?);
|
|
|
|
};
|
|
|
|
defer allocator.free(bucket);
|
|
|
|
const location = blk: {
|
|
|
|
const result = try aws.Request(services.s3.get_bucket_location).call(.{
|
|
|
|
.bucket = bucket,
|
|
|
|
}, options);
|
|
|
|
defer result.deinit();
|
|
|
|
const location = result.response.location_constraint.?;
|
2023-08-29 18:29:50 +00:00
|
|
|
std.log.info("GetBucketLocation request id: {s}", .{result.response_metadata.request_id});
|
2023-08-29 19:47:22 +00:00
|
|
|
std.log.info("location: {s}", .{location});
|
2022-06-06 01:34:39 +00:00
|
|
|
break :blk try allocator.dupe(u8, location);
|
|
|
|
};
|
|
|
|
defer allocator.free(location);
|
2023-08-27 18:54:31 +00:00
|
|
|
|
2022-06-06 01:34:39 +00:00
|
|
|
const s3opts = aws.Options{
|
|
|
|
.region = location,
|
|
|
|
.client = client,
|
|
|
|
};
|
2023-08-28 00:36:26 +00:00
|
|
|
{
|
|
|
|
const result = try aws.Request(services.s3.put_object).call(.{
|
|
|
|
.bucket = bucket,
|
|
|
|
.key = key,
|
|
|
|
.content_type = "text/plain",
|
|
|
|
.body = "bar",
|
|
|
|
.storage_class = "STANDARD",
|
|
|
|
}, s3opts);
|
2023-08-29 19:47:22 +00:00
|
|
|
std.log.info("PutObject Request id: {s}", .{result.response_metadata.request_id});
|
|
|
|
std.log.info("PutObject etag: {s}", .{result.response.e_tag.?});
|
2023-08-28 00:36:26 +00:00
|
|
|
defer result.deinit();
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// Note that boto appears to redirect by default, but java
|
|
|
|
// does not. We will not
|
|
|
|
const result = try aws.Request(services.s3.get_object).call(.{
|
|
|
|
.bucket = bucket,
|
|
|
|
.key = key,
|
|
|
|
}, s3opts);
|
2023-08-29 19:47:22 +00:00
|
|
|
std.log.info("GetObject Request id: {s}", .{result.response_metadata.request_id});
|
|
|
|
std.log.info("GetObject Body: {s}", .{result.response.body.?});
|
|
|
|
std.log.info("GetObject etag: {s}", .{result.response.e_tag.?});
|
2023-08-28 00:36:26 +00:00
|
|
|
std.log.info("GetObject last modified (seconds since epoch): {d}", .{result.response.last_modified.?});
|
|
|
|
defer result.deinit();
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const result = try aws.Request(services.s3.delete_object).call(.{
|
|
|
|
.bucket = bucket,
|
|
|
|
.key = key,
|
|
|
|
}, s3opts);
|
2023-08-29 19:47:22 +00:00
|
|
|
std.log.info("DeleteObject Request id: {s}", .{result.response_metadata.request_id});
|
2023-08-28 00:36:26 +00:00
|
|
|
defer result.deinit();
|
|
|
|
}
|
2022-06-06 01:34:39 +00:00
|
|
|
{
|
|
|
|
const result = try aws.Request(services.s3.list_objects).call(.{
|
|
|
|
.bucket = bucket,
|
|
|
|
}, s3opts);
|
2023-08-29 19:47:22 +00:00
|
|
|
std.log.info("ListObject Request id: {s}", .{result.response_metadata.request_id});
|
2022-06-06 01:34:39 +00:00
|
|
|
std.log.info("Object count: {d}", .{result.response.contents.?.len});
|
|
|
|
defer result.deinit();
|
|
|
|
}
|
|
|
|
},
|
2021-06-24 01:23:07 +00:00
|
|
|
}
|
|
|
|
std.log.info("===== End Test: {s} =====\n", .{@tagName(t)});
|
2021-04-27 18:24:01 +00:00
|
|
|
}
|
|
|
|
|
2021-06-24 01:23:07 +00:00
|
|
|
// if (test_twice) {
|
|
|
|
// std.time.sleep(1000 * std.time.ns_per_ms);
|
|
|
|
// std.log.info("second request", .{});
|
|
|
|
//
|
|
|
|
// var client2 = aws.Aws.init(allocator);
|
|
|
|
// defer client2.deinit();
|
|
|
|
// const resp2 = try client2.call(services.sts.get_caller_identity.Request{}, options); // catch here and try alloc?
|
|
|
|
// defer resp2.deinit();
|
|
|
|
// }
|
2021-04-27 18:24:01 +00:00
|
|
|
|
2021-06-24 01:23:07 +00:00
|
|
|
std.log.info("===== Tests complete =====", .{});
|
2021-04-27 18:24:01 +00:00
|
|
|
}
|
2023-08-29 18:24:34 +00:00
|
|
|
|
upgrade to nominated zig 2024.3.0-mach (0.12.0-dev.3180+83e578a18)
There were significant changes to the way HTTP operates since 0.11,
effecting client operations, but more substantially, the server
implementation, which effected the test harness.
std.http.Headers was removed, including the getFirstValue function, which
needed to be replicated. On the plus side, a std.http.Header struct was
added, identical to our own structure, so I have removed out own header
in favor of stdlib.
On the Http client side, I have switched to use the fetch API. Proxy
support is built in, but we are using (mostly) our own implementation
for now, with the remaining conversion left as a TODO item. Raw URIs are
now supported, so the workaround for issue 17015 has been removed. Large
payloads should also be fixed, but this has not been tested.
The standard library now adds the content-length header
(unconditionally), which is a decision of dubious nature. I have removed
the addition of content-length, which also means it is not present
during signing. This should be allowed.
Dependency loop on fieldTransformer was fixed. This should have been
a problem on zig 0.11, but was not. This effected the API for the json
parsing, but we were not using that. At the call site, these did not
need to be specified as references.
With the http server no longer doing all the allocations it once was,
the test harness now has a lot more allocations to perform. To alleviate
the bookeeping, this was moved to an Arena allocator. The client,
which is really what is under test, continues to use the allocator
passed.
2024-04-02 16:13:45 +00:00
|
|
|
fn proxyFromString(string: []const u8) !std.http.Client.Proxy {
|
|
|
|
var rc = std.http.Client.Proxy{
|
2023-08-29 18:24:34 +00:00
|
|
|
.protocol = undefined,
|
|
|
|
.host = undefined,
|
upgrade to nominated zig 2024.3.0-mach (0.12.0-dev.3180+83e578a18)
There were significant changes to the way HTTP operates since 0.11,
effecting client operations, but more substantially, the server
implementation, which effected the test harness.
std.http.Headers was removed, including the getFirstValue function, which
needed to be replicated. On the plus side, a std.http.Header struct was
added, identical to our own structure, so I have removed out own header
in favor of stdlib.
On the Http client side, I have switched to use the fetch API. Proxy
support is built in, but we are using (mostly) our own implementation
for now, with the remaining conversion left as a TODO item. Raw URIs are
now supported, so the workaround for issue 17015 has been removed. Large
payloads should also be fixed, but this has not been tested.
The standard library now adds the content-length header
(unconditionally), which is a decision of dubious nature. I have removed
the addition of content-length, which also means it is not present
during signing. This should be allowed.
Dependency loop on fieldTransformer was fixed. This should have been
a problem on zig 0.11, but was not. This effected the API for the json
parsing, but we were not using that. At the call site, these did not
need to be specified as references.
With the http server no longer doing all the allocations it once was,
the test harness now has a lot more allocations to perform. To alleviate
the bookeeping, this was moved to an Arena allocator. The client,
which is really what is under test, continues to use the allocator
passed.
2024-04-02 16:13:45 +00:00
|
|
|
.authorization = null,
|
|
|
|
.port = undefined,
|
|
|
|
.supports_connect = true, // TODO: Is this a good default?
|
2023-08-29 18:24:34 +00:00
|
|
|
};
|
|
|
|
var remaining: []const u8 = string;
|
|
|
|
if (std.mem.startsWith(u8, string, "http://")) {
|
|
|
|
remaining = remaining["http://".len..];
|
|
|
|
rc.protocol = .plain;
|
upgrade to nominated zig 2024.3.0-mach (0.12.0-dev.3180+83e578a18)
There were significant changes to the way HTTP operates since 0.11,
effecting client operations, but more substantially, the server
implementation, which effected the test harness.
std.http.Headers was removed, including the getFirstValue function, which
needed to be replicated. On the plus side, a std.http.Header struct was
added, identical to our own structure, so I have removed out own header
in favor of stdlib.
On the Http client side, I have switched to use the fetch API. Proxy
support is built in, but we are using (mostly) our own implementation
for now, with the remaining conversion left as a TODO item. Raw URIs are
now supported, so the workaround for issue 17015 has been removed. Large
payloads should also be fixed, but this has not been tested.
The standard library now adds the content-length header
(unconditionally), which is a decision of dubious nature. I have removed
the addition of content-length, which also means it is not present
during signing. This should be allowed.
Dependency loop on fieldTransformer was fixed. This should have been
a problem on zig 0.11, but was not. This effected the API for the json
parsing, but we were not using that. At the call site, these did not
need to be specified as references.
With the http server no longer doing all the allocations it once was,
the test harness now has a lot more allocations to perform. To alleviate
the bookeeping, this was moved to an Arena allocator. The client,
which is really what is under test, continues to use the allocator
passed.
2024-04-02 16:13:45 +00:00
|
|
|
rc.port = 80;
|
2023-08-29 18:24:34 +00:00
|
|
|
} else if (std.mem.startsWith(u8, string, "https://")) {
|
|
|
|
remaining = remaining["https://".len..];
|
upgrade to nominated zig 2024.3.0-mach (0.12.0-dev.3180+83e578a18)
There were significant changes to the way HTTP operates since 0.11,
effecting client operations, but more substantially, the server
implementation, which effected the test harness.
std.http.Headers was removed, including the getFirstValue function, which
needed to be replicated. On the plus side, a std.http.Header struct was
added, identical to our own structure, so I have removed out own header
in favor of stdlib.
On the Http client side, I have switched to use the fetch API. Proxy
support is built in, but we are using (mostly) our own implementation
for now, with the remaining conversion left as a TODO item. Raw URIs are
now supported, so the workaround for issue 17015 has been removed. Large
payloads should also be fixed, but this has not been tested.
The standard library now adds the content-length header
(unconditionally), which is a decision of dubious nature. I have removed
the addition of content-length, which also means it is not present
during signing. This should be allowed.
Dependency loop on fieldTransformer was fixed. This should have been
a problem on zig 0.11, but was not. This effected the API for the json
parsing, but we were not using that. At the call site, these did not
need to be specified as references.
With the http server no longer doing all the allocations it once was,
the test harness now has a lot more allocations to perform. To alleviate
the bookeeping, this was moved to an Arena allocator. The client,
which is really what is under test, continues to use the allocator
passed.
2024-04-02 16:13:45 +00:00
|
|
|
rc.port = 443;
|
2023-08-29 18:24:34 +00:00
|
|
|
rc.protocol = .tls;
|
|
|
|
} else return error.InvalidScheme;
|
|
|
|
var split_iterator = std.mem.split(u8, remaining, ":");
|
|
|
|
rc.host = std.mem.trimRight(u8, split_iterator.first(), "/");
|
|
|
|
if (split_iterator.next()) |port|
|
|
|
|
rc.port = try std.fmt.parseInt(u16, port, 10);
|
|
|
|
return rc;
|
|
|
|
}
|
2023-08-05 19:41:04 +00:00
|
|
|
fn typeForField(comptime T: type, comptime field_name: []const u8) !type {
|
2021-08-25 00:02:28 +00:00
|
|
|
const ti = @typeInfo(T);
|
|
|
|
switch (ti) {
|
|
|
|
.Struct => {
|
|
|
|
inline for (ti.Struct.fields) |field| {
|
|
|
|
if (std.mem.eql(u8, field.name, field_name))
|
2023-08-05 19:41:04 +00:00
|
|
|
return field.type;
|
2021-08-25 00:02:28 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
else => return error.TypeIsNotAStruct, // should not hit this
|
|
|
|
}
|
|
|
|
return error.FieldNotFound;
|
|
|
|
}
|
2021-05-13 22:53:53 +00:00
|
|
|
|
2021-06-24 01:23:07 +00:00
|
|
|
// TODO: Move into json.zig
|
2021-05-13 22:53:53 +00:00
|
|
|
pub fn jsonFun() !void {
|
|
|
|
// Standard behavior
|
|
|
|
const payload =
|
|
|
|
\\{"GetCallerIdentityResponse":{"GetCallerIdentityResult":{"Account":"0123456789","Arn":"arn:aws:iam::0123456789:user/test","UserId":"MYUSERID"},"ResponseMetadata":{"RequestId":"3b80a99b-7df8-4bcb-96ee-b2759878a5f2"}}}
|
|
|
|
;
|
|
|
|
const Ret3 = struct {
|
|
|
|
getCallerIdentityResponse: struct { getCallerIdentityResult: struct { account: []u8, arn: []u8, user_id: []u8 }, responseMetadata: struct { requestId: []u8 } },
|
|
|
|
};
|
|
|
|
var stream3 = json.TokenStream.init(payload);
|
|
|
|
const res3 = json.parse(Ret3, &stream3, .{
|
|
|
|
.allocator = std.heap.c_allocator,
|
|
|
|
.allow_camel_case_conversion = true, // new option
|
|
|
|
.allow_snake_case_conversion = true, // new option
|
|
|
|
.allow_unknown_fields = true, // new option
|
|
|
|
}) catch unreachable;
|
|
|
|
std.log.info("{}", .{res3});
|
2023-08-14 17:06:28 +00:00
|
|
|
std.log.info("{any}", .{res3.getCallerIdentityResponse.getCallerIdentityResult.user_id});
|
2021-05-13 22:53:53 +00:00
|
|
|
}
|