Skip to content

Commit

Permalink
support supabase s3
Browse files Browse the repository at this point in the history
  • Loading branch information
cirospaciari committed Feb 8, 2025
1 parent 0da7025 commit 3234209
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 18 deletions.
4 changes: 2 additions & 2 deletions src/env_loader.zig
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,9 @@ pub const Loader = struct {
region = region_;
}
if (this.get("S3_ENDPOINT")) |endpoint_| {
endpoint = bun.URL.parse(endpoint_).host;
endpoint = bun.URL.parse(endpoint_).hostWithPath();
} else if (this.get("AWS_ENDPOINT")) |endpoint_| {
endpoint = bun.URL.parse(endpoint_).host;
endpoint = bun.URL.parse(endpoint_).hostWithPath();
}
if (this.get("S3_BUCKET")) |bucket_| {
bucket = bucket_;
Expand Down
40 changes: 24 additions & 16 deletions src/s3/credentials.zig
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ pub const S3Credentials = struct {
new_credentials._endpointSlice = str.toUTF8(bun.default_allocator);
const endpoint = new_credentials._endpointSlice.?.slice();
const url = bun.URL.parse(endpoint);
const normalized_endpoint = url.host;
const normalized_endpoint = url.hostWithPath();
if (normalized_endpoint.len > 0) {
new_credentials.credentials.endpoint = normalized_endpoint;

Expand Down Expand Up @@ -524,7 +524,29 @@ pub const S3Credentials = struct {
var bucket_buffer: [63]u8 = undefined;
bucket = encodeURIComponent(bucket, &bucket_buffer, false) catch return error.InvalidPath;
path = encodeURIComponent(path, &path_buffer, false) catch return error.InvalidPath;
const normalizedPath = std.fmt.bufPrint(&normalized_path_buffer, "/{s}/{s}", .{ bucket, path }) catch return error.InvalidPath;
// Default to https. Only use http if they explicit pass "http://" as the endpoint.
const protocol = if (this.insecure_http) "http" else "https";

// detect service name and host from region or endpoint
var endpoint = this.endpoint;
var extra_path: []const u8 = "";
const host = brk_host: {
if (this.endpoint.len > 0) {
if (this.endpoint.len >= 2048) return error.InvalidEndpoint;
var host = this.endpoint;
if (bun.strings.indexOf(this.endpoint, "/")) |index| {
host = this.endpoint[0..index];
extra_path = this.endpoint[index..];
}
// only the host part is needed here
break :brk_host try bun.default_allocator.dupe(u8, host);
} else {
endpoint = try std.fmt.allocPrint(bun.default_allocator, "s3.{s}.amazonaws.com", .{region});
break :brk_host endpoint;
}
};
errdefer bun.default_allocator.free(host);
const normalizedPath = std.fmt.bufPrint(&normalized_path_buffer, "{s}/{s}/{s}", .{ extra_path, bucket, path }) catch return error.InvalidPath;

const date_result = getAMZDate(bun.default_allocator);
const amz_date = date_result.date;
Expand Down Expand Up @@ -595,22 +617,8 @@ pub const S3Credentials = struct {
}
};

// Default to https. Only use http if they explicit pass "http://" as the endpoint.
const protocol = if (this.insecure_http) "http" else "https";

// detect service name and host from region or endpoint
const host = brk_host: {
if (this.endpoint.len > 0) {
if (this.endpoint.len >= 512) return error.InvalidEndpoint;
break :brk_host try bun.default_allocator.dupe(u8, this.endpoint);
} else {
break :brk_host try std.fmt.allocPrint(bun.default_allocator, "s3.{s}.amazonaws.com", .{region});
}
};
const service_name = "s3";

errdefer bun.default_allocator.free(host);

const aws_content_hash = if (content_hash) |hash| hash else ("UNSIGNED-PAYLOAD");
var tmp_buffer: [4096]u8 = undefined;

Expand Down
14 changes: 14 additions & 0 deletions src/url.zig
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ pub const URL = struct {
pub fn isFile(this: *const URL) bool {
return strings.eqlComptime(this.protocol, "file");
}
/// host + path without the ending slash, protocol, searchParams and hash
pub fn hostWithPath(this: *const URL) []const u8 {
if (this.host.len > 0) {
if (this.path.len > 1) {
const end = @intFromPtr(this.path.ptr) + this.path.len;
const start = @intFromPtr(this.host.ptr);
const len: usize = end - start - (if (bun.strings.endsWithComptime(this.path, "/")) @as(usize, 1) else @as(usize, 0));
const ptr: [*]u8 = @ptrFromInt(start);
return ptr[0..len];
}
return this.host;
}
return "";
}

pub fn isBlob(this: *const URL) bool {
return this.href.len == JSC.WebCore.ObjectURLRegistry.specifier_len and strings.hasPrefixComptime(this.href, "blob:");
Expand Down
7 changes: 7 additions & 0 deletions test/js/bun/s3/s3.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ const allCredentials = [
bucket: getSecret("S3_R2_BUCKET"),
service: "R2" as string,
},
{
accessKeyId: getSecret("SUPABASE_ACCESS_KEY"),
secretAccessKey: getSecret("SUPABASE_SECRET_KEY"),
endpoint: getSecret("SUPABASE_ENDPOINT"),
bucket: getSecret("SUPABASE_BUCKET"),
service: "supabase" as string,
},
];

if (isDockerEnabled()) {
Expand Down

0 comments on commit 3234209

Please sign in to comment.