Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(s3Client): add support for ListObjectsV2 action #16948

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Inqnuam
Copy link
Contributor

@Inqnuam Inqnuam commented Jan 31, 2025

What does this PR do?

This PR adds support for S3 ListObjectsV2 action.
Same input/output as @aws-sdk/s3-client.

Closes #16495
May be helpful for #8947

  • Documentation or TypeScript types
  • Code changes

How did you verify your code works?

I wrote automated tests

  • I included a test for the new code, or existing tests cover it
  • I ran my tests locally and they pass (bun-debug test test/js/bun/s3/s3-list-objects.test.ts)
  • I ran my tests on AWS and they pass

If Zig files changed:

  • I checked the lifetime of memory allocated to verify it's (1) freed and (2) only freed when it should be
  • I included a test for the new code, or an existing test covers it
  • JSValue used outside outside of the stack is either wrapped in a JSC.Strong or is JSValueProtect'ed
  • I wrote TypeScript/JavaScript tests and they pass locally (bun-debug test test/js/bun/s3/s3-list-objects.test.ts)

If new methods, getters, or setters were added to a publicly exposed class:

  • I added TypeScript types for the new methods, getters, or setters

@zshzebra
Copy link

zshzebra commented Feb 2, 2025

Hopefully a maintainer can get to this soon. I would love to see this added.

@@ -1813,6 +1813,106 @@ declare module "bun" {
* const url = bucket.presign("file.pdf");
* await bucket.unlink("old.txt");
*/
interface S3ListObjectsOptions {
/** Limits the response to keys that begin with the specified prefix. */
Prefix?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The names of fields in the types should start in lower cased.

*
* You can use the request parameters as selection criteria to return a subset of the objects in a bucket.
*/
listObjects(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just list would be better instead of listObjects

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about if we want to implement list buckets later ?

const result = this.signRequest(.{
.path = "",
.method = .GET,
.search_params = search_params.slice(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

search_params is leaking memory here, we need to free it after calling signRequest

@@ -517,7 +536,7 @@ pub const S3Credentials = struct {
}

// if we allow path.len == 0 it will list the bucket for now we disallow
if (path.len == 0) return error.InvalidPath;
if (!isComplexeRequest and path.len == 0) return error.InvalidPath;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not right we cannot allow bucket unless we are listing a bucket you can pass a comptime bool for this case

} else {
break :brk_canonical try std.fmt.bufPrint(&tmp_buffer, "{s}\n{s}\n{s}\nhost:{s}\nx-amz-content-sha256:{s}\nx-amz-date:{s}\n\n{s}\n{s}", .{ method_name, normalizedPath, if (search_params) |p| p[1..] else "", host, aws_content_hash, amz_date, signed_headers, aws_content_hash });
if (session_token) |token| {
break :brk_canonical try std.fmt.bufPrint(&tmp_buffer, "{s}\n{s}\n{s}\nhost:{s}\nx-amz-content-sha256:{s}\nx-amz-date:{s}\nx-amz-security-token:{s}\n\n{s}\n{s}", .{ method_name, normalizedPath, if (search_params) |p| p[1..] else "", host, aws_content_hash, amz_date, token, signed_headers, aws_content_hash });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this conditions are getting too big we should break to a slow path when we actualy sort in the right order instead of if/else stuff

Copy link
Contributor Author

@Inqnuam Inqnuam Feb 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed this is unmaintainable and error prone
I wrote an implementation of the entire SigV4 with dynamic values, need deep testing before merging here

import { describe, it, expect } from "bun:test";
import { randomUUIDv7, S3Client, S3ListObjectsResponse, S3Options } from "bun";

const options: S3Options = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should add tests using the CI credentials take a look on the s3.tests.ts

@@ -3596,6 +3596,58 @@ pub const Blob = struct {

return value;
}

pub fn listObjects(this: *@This(), store: *Store, globalThis: *JSC.JSGlobalObject, listOptions: JSValue, extra_options: ?JSValue) bun.JSError!JSValue {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be in S3File.zig not in blob.zig

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

s3 list function
3 participants