rest_xml support, minus s3
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
73d056e845
commit
357c583e9b
14
README.md
14
README.md
|
@ -2,8 +2,7 @@
|
|||
|
||||
[![Build Status](https://drone.lerch.org/api/badges/lobo/aws-sdk-for-zig/status.svg?ref=refs/heads/master)](https://drone.lerch.org/api/badges/lobo/aws-sdk-for-zig/)
|
||||
|
||||
This SDK currently supports all AWS services. restXml protocol support (4
|
||||
services including S3), is still new, with lots of gaps. See TODO list below.
|
||||
This SDK currently supports all AWS services except S3. See TODO list below.
|
||||
|
||||
Current executable size for the demo is 1.7M (90k of which is the AWS PEM file,
|
||||
and approximately 600K for XML services) after compiling with -Drelease-safe and
|
||||
|
@ -43,14 +42,15 @@ for posterity, and supports x86_64 linux. The old branch is deprecated.
|
|||
|
||||
## Limitations
|
||||
|
||||
There are many nuances of AWS V4 signature calculation. Parts of S3 are not supported
|
||||
because it uses many of these test cases. WebIdentityToken is not yet
|
||||
implemented.
|
||||
There are many nuances of AWS V4 signature calculation. S3 is not supported
|
||||
because it uses many of these edge cases. Also endpoint calculation is special
|
||||
for S3. WebIdentityToken is not yet implemented.
|
||||
|
||||
TODO List:
|
||||
|
||||
* Complete development of [AWS restXml protocol](https://awslabs.github.io/smithy/1.0/spec/aws/aws-restxml-protocol.html).
|
||||
Includes S3. Total service count 4.
|
||||
* Implement initial S3 support. This involves:
|
||||
* Implementation of AWS SigV4 signature calculation for S3, which is unique
|
||||
* Implementation of S3 endpoint calculation, which is also unique to this service
|
||||
* Bump to zig 0.9.1. iguanaTLS, used in zFetch is still [working out 0.9.1 issues](https://github.com/alexnask/iguanaTLS/pull/29)
|
||||
* Implement sigv4a signing
|
||||
* Implement jitter/exponential backoff
|
||||
|
|
48
src/aws.zig
48
src/aws.zig
|
@ -268,6 +268,13 @@ pub fn Request(comptime action: anytype) type {
|
|||
else
|
||||
ServerResponse(action);
|
||||
|
||||
const NullType: type = u0; // This is a small hack, yes...
|
||||
const SRawResponse = if (Self.service_meta.aws_protocol != .query and
|
||||
std.meta.fields(SResponse).len == 1)
|
||||
std.meta.fields(SResponse)[0].field_type
|
||||
else
|
||||
NullType;
|
||||
|
||||
const parser_options = json.ParseOptions{
|
||||
.allocator = options.client.allocator,
|
||||
.allow_camel_case_conversion = true, // new option
|
||||
|
@ -288,7 +295,37 @@ pub fn Request(comptime action: anytype) type {
|
|||
|
||||
var stream = json.TokenStream.init(response.body);
|
||||
|
||||
const parsed_response = json.parse(SResponse, &stream, parser_options) catch |e| {
|
||||
const start = std.mem.indexOf(u8, response.body, "\"") orelse 0; // Should never be 0
|
||||
if (start == 0) log.warn("Response body missing json key?!", .{});
|
||||
var end = std.mem.indexOf(u8, response.body[start + 1 ..], "\"") orelse 0;
|
||||
if (end == 0) log.warn("Response body only has one double quote?!", .{});
|
||||
end = end + start + 1;
|
||||
|
||||
const key = response.body[start + 1 .. end];
|
||||
log.debug("First json key: {s}", .{key});
|
||||
const foundNormalJsonResponse = std.mem.eql(u8, key, action.action_name ++ "Response");
|
||||
const parsed_response_ptr = blk: {
|
||||
if (SRawResponse == NullType or foundNormalJsonResponse)
|
||||
break :blk &(json.parse(SResponse, &stream, parser_options) catch |e| {
|
||||
log.err(
|
||||
\\Call successful, but unexpected response from service.
|
||||
\\This could be the result of a bug or a stale set of code generated
|
||||
\\service models.
|
||||
\\
|
||||
\\Model Type: {s}
|
||||
\\
|
||||
\\Response from server:
|
||||
\\
|
||||
\\{s}
|
||||
\\
|
||||
, .{ SResponse, response.body });
|
||||
return e;
|
||||
});
|
||||
|
||||
log.debug("Appears server has provided a raw response", .{});
|
||||
const ptr = try options.client.allocator.create(SResponse);
|
||||
@field(ptr.*, std.meta.fields(SResponse)[0].name) =
|
||||
json.parse(SRawResponse, &stream, parser_options) catch |e| {
|
||||
log.err(
|
||||
\\Call successful, but unexpected response from service.
|
||||
\\This could be the result of a bug or a stale set of code generated
|
||||
|
@ -303,6 +340,15 @@ pub fn Request(comptime action: anytype) type {
|
|||
, .{ SResponse, response.body });
|
||||
return e;
|
||||
};
|
||||
break :blk ptr;
|
||||
};
|
||||
|
||||
// This feels like it should result in a use after free, but it
|
||||
// seems to be working?
|
||||
defer if (!(SRawResponse == NullType or foundNormalJsonResponse))
|
||||
options.client.allocator.destroy(parsed_response_ptr);
|
||||
|
||||
const parsed_response = parsed_response_ptr.*;
|
||||
|
||||
// TODO: Figure out this hack
|
||||
// the code setting the response about 10 lines down will trigger
|
||||
|
|
11
src/main.zig
11
src/main.zig
|
@ -49,6 +49,7 @@ const Tests = enum {
|
|||
rest_json_1_query_with_input,
|
||||
rest_json_1_work_with_lambda,
|
||||
rest_xml_no_input,
|
||||
rest_xml_anything_but_s3,
|
||||
};
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
|
@ -89,7 +90,7 @@ pub fn main() anyerror!void {
|
|||
};
|
||||
defer client.deinit();
|
||||
|
||||
const services = aws.Services(.{ .sts, .ec2, .dynamo_db, .ecs, .lambda, .sqs, .s3 }){};
|
||||
const services = aws.Services(.{ .sts, .ec2, .dynamo_db, .ecs, .lambda, .sqs, .s3, .cloudfront }){};
|
||||
|
||||
for (tests.items) |t| {
|
||||
std.log.info("===== Start Test: {s} =====", .{@tagName(t)});
|
||||
|
@ -221,6 +222,14 @@ pub fn main() anyerror!void {
|
|||
std.log.info("request id: {s}", .{result.response_metadata.request_id});
|
||||
std.log.info("bucket count: {d}", .{result.response.buckets.?.len});
|
||||
},
|
||||
.rest_xml_anything_but_s3 => {
|
||||
const result = try client.call(services.cloudfront.list_key_groups.Request{}, options);
|
||||
defer result.deinit();
|
||||
std.log.info("request id: {s}", .{result.response_metadata.request_id});
|
||||
const list = result.response.key_group_list.?;
|
||||
std.log.info("key group list max: {d}", .{list.max_items});
|
||||
std.log.info("key group quantity: {d}", .{list.quantity});
|
||||
},
|
||||
}
|
||||
std.log.info("===== End Test: {s} =====\n", .{@tagName(t)});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user