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: add headBucket method #36

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3475364
feat: add createBucket method
c4spar Nov 6, 2021
d96b424
move createBucket method to S3 class
c4spar Nov 7, 2021
58e18d8
remove unused interface
c4spar Nov 7, 2021
86575ac
add missing export in mod.ts
c4spar Nov 7, 2021
e8daafe
rename utils.ts to request.ts
c4spar Nov 7, 2021
597963f
feat: add headBucket method
c4spar Nov 7, 2021
0007c9e
set minio region
c4spar Nov 7, 2021
1dafea7
make path optional in S3RequestOptions
c4spar Nov 8, 2021
355e997
remove space from header name
c4spar Nov 9, 2021
bffc48e
add getBucket method
c4spar Nov 11, 2021
c9c3104
fix example
c4spar Nov 11, 2021
d719bce
re-format
c4spar Nov 11, 2021
00c16b8
update readme
c4spar Nov 11, 2021
be06926
add missing export
c4spar Nov 11, 2021
f0fab70
update test's
c4spar Nov 11, 2021
7408059
rename bucket
c4spar Nov 12, 2021
a4806c2
update docs
c4spar Nov 12, 2021
9b39bd0
add CreateBucketConfiguration
c4spar Nov 12, 2021
573c19a
move locationConstraint to CreateBucketOptions
c4spar Nov 12, 2021
7837e4d
export LocationConstraint
c4spar Nov 12, 2021
8ca519e
Revert "move locationConstraint to CreateBucketOptions"
c4spar Nov 12, 2021
9af711f
fix example
c4spar Nov 12, 2021
14fb72c
update docs
c4spar Nov 12, 2021
1bf7d40
fix type
c4spar Nov 12, 2021
16697d0
Merge remote-tracking branch 'origin/feat/create-bucket' into feat/he…
c4spar Nov 12, 2021
36013dd
return S3Bucket instance and update docs
c4spar Nov 12, 2021
590f051
update test messages
c4spar Nov 13, 2021
9045d32
cleanup
c4spar Nov 13, 2021
9c81599
Merge remote-tracking branch 'origin/feat/create-bucket' into feat/he…
c4spar Nov 13, 2021
6b55d18
Merge remote-tracking branch 'origin/main' into feat/head-bucket
c4spar Nov 23, 2021
1ab4cfa
cleanup
c4spar Nov 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type {
DeleteObjectResponse,
GetObjectOptions,
GetObjectResponse,
HeadBucketOptions,
HeadObjectResponse,
ListAllObjectsOptions,
ListObjectsOptions,
Expand Down
40 changes: 39 additions & 1 deletion src/client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AWSSignerV4 } from "../deps.ts";
import type { CreateBucketOptions } from "./types.ts";
import type { CreateBucketOptions, HeadBucketOptions } from "./types.ts";
import { S3Error } from "./error.ts";
import { S3Bucket } from "./bucket.ts";
import { doRequest, encoder } from "./request.ts";
Expand Down Expand Up @@ -50,6 +50,44 @@ export class S3 {
});
}

/**
* Determine if a bucket exists and if you have permission to access it.
* The method returns a S3Bucket if the bucket exists and if you have
* permission to access it. If the bucket does not exist or you do not have
* permission to access it an `S3Error` is thrown.
*
* To use this operation, you must have permissions to perform the
* s3:ListBucket action. The bucket owner has this permission by default and
* can grant this permission to others.
*/
async headBucket(
bucket: string,
options?: HeadBucketOptions,
): Promise<S3Bucket> {
const headers: Params = {};

if (options?.expectedBucketOwner) {
headers["x-amz-expected-bucket-owner"] = options.expectedBucketOwner;
}

const resp = await doRequest({
host: this.#host,
signer: this.#signer,
path: bucket,
method: "HEAD",
headers,
});

if (resp.status !== 200) {
throw new S3Error(
`Failed to get bucket "${bucket}": ${resp.status} ${resp.statusText}`,
await resp.text(),
);
}

return this.getBucket(bucket);
}

/**
* Creates a new S3 bucket. By default, the bucket is created in the region
* specified with the S3 options. If not specified the US East (N. Virginia)
Expand Down
24 changes: 23 additions & 1 deletion src/client_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const s3 = new S3({
});

Deno.test({
name: "[client] should get an existing bucket",
name: "[client] should get a bucket instance",
async fn() {
const bucket = await s3.getBucket("test");

Expand All @@ -26,6 +26,28 @@ Deno.test({
},
});

Deno.test({
name: "[client] should determine if a bucket exists",
async fn() {
const bucket = await s3.headBucket("test");

// Check if returned bucket instance is working.
await bucket.putObject("test", encoder.encode("test"));
const resp = await bucket.getObject("test");
const body = await new Response(resp?.body).text();
assertEquals(body, "test");

await assertThrowsAsync(
() => s3.headBucket("not-existing-bucket"),
S3Error,
'Failed to get bucket "not-existing-bucket": 404 Not Found',
);

// teardown
await bucket.deleteObject("test");
},
});

Deno.test({
name: "[client] should create a new bucket",
async fn() {
Expand Down
9 changes: 9 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,15 @@ export interface DeleteObjectResponse {
deleteMarker: boolean;
}

export interface HeadBucketOptions {
/**
* The account ID of the expected bucket owner. If the bucket is owned by a
* different account, the request will fail with an HTTP 403 (Access Denied)
* error.
*/
expectedBucketOwner?: string;
}

export type LocationConstraint =
| "af-south-1"
| "ap-east-1"
Expand Down