This commit is contained in:
parent
a662f6f674
commit
8d852e8084
|
@ -2,8 +2,6 @@
|
|||
|
||||
[![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. S3 has basic support
|
||||
|
||||
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
|
||||
[stripping the executable after compilation](https://github.com/ziglang/zig/issues/351).
|
||||
|
@ -42,13 +40,10 @@ for posterity, and supports x86_64 linux. The old branch is deprecated.
|
|||
|
||||
## Limitations
|
||||
|
||||
There are many nuances of AWS V4 signature calculation, and not all edge cases
|
||||
of S3 are handled. WebIdentityToken is not yet implemented.
|
||||
WebIdentityToken is not yet implemented.
|
||||
|
||||
TODO List:
|
||||
|
||||
* Implement more robust S3 support. Keys with slashes in the name are currently
|
||||
causing a SignatureDoesNotMatch error
|
||||
* 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
|
||||
|
|
34
src/aws.zig
34
src/aws.zig
|
@ -110,7 +110,13 @@ pub fn Request(comptime action: anytype) type {
|
|||
log.debug("Rest method: '{s}'", .{aws_request.method});
|
||||
log.debug("Rest success code: '{d}'", .{Action.http_config.success_code});
|
||||
log.debug("Rest raw uri: '{s}'", .{Action.http_config.uri});
|
||||
aws_request.path = try buildPath(options.client.allocator, Action.http_config.uri, ActionRequest, request);
|
||||
aws_request.path = try buildPath(
|
||||
options.client.allocator,
|
||||
Action.http_config.uri,
|
||||
ActionRequest,
|
||||
request,
|
||||
!std.mem.eql(u8, Self.service_meta.sdk_id, "S3"),
|
||||
);
|
||||
defer options.client.allocator.free(aws_request.path);
|
||||
log.debug("Rest processed uri: '{s}'", .{aws_request.path});
|
||||
// TODO: Make sure this doesn't get escaped here for S3
|
||||
|
@ -883,7 +889,13 @@ fn queryFieldTransformer(field_name: []const u8, encoding_options: url.EncodingO
|
|||
return try case.snakeToPascal(encoding_options.allocator.?, field_name);
|
||||
}
|
||||
|
||||
fn buildPath(allocator: std.mem.Allocator, raw_uri: []const u8, comptime ActionRequest: type, request: anytype) ![]const u8 {
|
||||
fn buildPath(
|
||||
allocator: std.mem.Allocator,
|
||||
raw_uri: []const u8,
|
||||
comptime ActionRequest: type,
|
||||
request: anytype,
|
||||
encode_slash: bool,
|
||||
) ![]const u8 {
|
||||
var buffer = try std.ArrayList(u8).initCapacity(allocator, raw_uri.len);
|
||||
// const writer = buffer.writer();
|
||||
defer buffer.deinit();
|
||||
|
@ -916,7 +928,7 @@ fn buildPath(allocator: std.mem.Allocator, raw_uri: []const u8, comptime ActionR
|
|||
replacement_writer,
|
||||
);
|
||||
const trimmed_replacement_val = std.mem.trim(u8, replacement_buffer.items, "\"");
|
||||
try uriEncode(trimmed_replacement_val, encoded_buffer.writer());
|
||||
try uriEncode(trimmed_replacement_val, encoded_buffer.writer(), encode_slash);
|
||||
try buffer.appendSlice(encoded_buffer.items);
|
||||
}
|
||||
}
|
||||
|
@ -929,12 +941,12 @@ fn buildPath(allocator: std.mem.Allocator, raw_uri: []const u8, comptime ActionR
|
|||
return buffer.toOwnedSlice();
|
||||
}
|
||||
|
||||
fn uriEncode(input: []const u8, writer: anytype) !void {
|
||||
fn uriEncode(input: []const u8, writer: anytype, encode_slash: bool) !void {
|
||||
for (input) |c|
|
||||
try uriEncodeByte(c, writer);
|
||||
try uriEncodeByte(c, writer, encode_slash);
|
||||
}
|
||||
|
||||
fn uriEncodeByte(char: u8, writer: anytype) !void {
|
||||
fn uriEncodeByte(char: u8, writer: anytype, encode_slash: bool) !void {
|
||||
switch (char) {
|
||||
'!' => _ = try writer.write("%21"),
|
||||
'#' => _ = try writer.write("%23"),
|
||||
|
@ -946,7 +958,7 @@ fn uriEncodeByte(char: u8, writer: anytype) !void {
|
|||
'*' => _ = try writer.write("%2A"),
|
||||
'+' => _ = try writer.write("%2B"),
|
||||
',' => _ = try writer.write("%2C"),
|
||||
'/' => _ = try writer.write("%2F"),
|
||||
'/' => _ = if (encode_slash) try writer.write("%2F") else try writer.write("/"),
|
||||
':' => _ = try writer.write("%3A"),
|
||||
';' => _ = try writer.write("%3B"),
|
||||
'=' => _ = try writer.write("%3D"),
|
||||
|
@ -1030,7 +1042,7 @@ fn addQueryArg(comptime ValueType: type, prefix: []const u8, key: []const u8, va
|
|||
fn addBasicQueryArg(prefix: []const u8, key: []const u8, value: anytype, writer: anytype) !bool {
|
||||
_ = try writer.write(prefix);
|
||||
// TODO: url escaping
|
||||
try uriEncode(key, writer);
|
||||
try uriEncode(key, writer, true);
|
||||
_ = try writer.write("=");
|
||||
try json.stringify(value, .{}, ignoringWriter(uriEncodingWriter(writer).writer(), '"').writer());
|
||||
return true;
|
||||
|
@ -1050,7 +1062,7 @@ pub fn UriEncodingWriter(comptime WriterType: type) type {
|
|||
const Self = @This();
|
||||
|
||||
pub fn write(self: *Self, bytes: []const u8) Error!usize {
|
||||
try uriEncode(bytes, self.child_stream);
|
||||
try uriEncode(bytes, self.child_stream, true);
|
||||
return bytes.len; // We say that all bytes are "written", even if they're not, as caller may be retrying
|
||||
}
|
||||
|
||||
|
@ -1193,7 +1205,7 @@ test "REST Json v1 buildpath substitutes" {
|
|||
.max_items = 1,
|
||||
};
|
||||
const input_path = "https://myhost/{MaxItems}/";
|
||||
const output_path = try buildPath(allocator, input_path, @TypeOf(request), request);
|
||||
const output_path = try buildPath(allocator, input_path, @TypeOf(request), request, true);
|
||||
defer allocator.free(output_path);
|
||||
try std.testing.expectEqualStrings("https://myhost/1/", output_path);
|
||||
}
|
||||
|
@ -1204,7 +1216,7 @@ test "REST Json v1 buildpath handles restricted characters" {
|
|||
.marker = ":",
|
||||
};
|
||||
const input_path = "https://myhost/{Marker}/";
|
||||
const output_path = try buildPath(allocator, input_path, @TypeOf(request), request);
|
||||
const output_path = try buildPath(allocator, input_path, @TypeOf(request), request, true);
|
||||
defer allocator.free(output_path);
|
||||
try std.testing.expectEqualStrings("https://myhost/%3A/", output_path);
|
||||
}
|
||||
|
|
|
@ -235,9 +235,8 @@ pub fn main() anyerror!void {
|
|||
std.log.info("key group quantity: {d}", .{list.quantity});
|
||||
},
|
||||
.rest_xml_work_with_s3 => {
|
||||
// TODO: Fix signature calculation mismatch with slashes
|
||||
// const key = "i/am/a/teapot/foo";
|
||||
const key = "foo";
|
||||
const key = "i/am/a/teapot/foo";
|
||||
// const key = "foo";
|
||||
|
||||
const bucket = blk: {
|
||||
const result = try client.call(services.s3.list_buckets.Request{}, options);
|
||||
|
|
Loading…
Reference in New Issue
Block a user