Skip to content

Commit f3fd665

Browse files
committed
fix: correctly populate ListObjectsResponse.commonPrefixes
1 parent 0af082b commit f3fd665

File tree

3 files changed

+59
-10
lines changed

3 files changed

+59
-10
lines changed

src/bucket.ts

+7-9
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ export class S3Bucket {
274274
if (options?.maxKeys) {
275275
params["max-keys"] = options.maxKeys.toString();
276276
}
277-
if (options?.prefix) {
277+
if (options?.prefix != null) {
278278
params["prefix"] = options.prefix;
279279
}
280280
if (options?.continuationToken) {
@@ -360,14 +360,8 @@ export class S3Bucket {
360360
prefix: extractContent(root, "Prefix"),
361361
delimiter: extractContent(root, "Delimiter"),
362362
maxKeys: maxkeys,
363-
commonPrefixes: extractField(
364-
root,
365-
"CommonPrefixes",
366-
)?.children.map<CommonPrefix>((prefix) => {
367-
return {
368-
prefix: extractContent(prefix, "Prefix"),
369-
};
370-
}),
363+
commonPrefixes: extractMultipleFields(root, "CommonPrefixes")
364+
.map((node) => ({ prefix: extractContent(node, "Prefix") })),
371365
encodingType: extractContent(root, "EncodingType"),
372366
keyCount: keycount,
373367
continuationToken: extractContent(root, "ContinuationToken"),
@@ -653,6 +647,10 @@ function extractField(node: Xml, name: string): Xml | undefined {
653647
return node.children.find((node) => node.name === name);
654648
}
655649

650+
function extractMultipleFields(node: Xml, name: string): Xml[] {
651+
return node.children.filter((node) => node.name === name);
652+
}
653+
656654
function extractContent(node: Xml, name: string): string | undefined {
657655
const field = extractField(node, name);
658656
const content = field?.content;

src/response_parsing_test.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { assertEquals } from "../test_deps.ts";
2+
import { S3Bucket } from "./bucket.ts";
3+
4+
const bucket: S3Bucket = Object.create(S3Bucket.prototype)
5+
6+
Deno.test("[response parsing]", async (t) => {
7+
await t.step("parseListObjectResponseXml", async (t) => {
8+
await t.step("commonPrefixes", () => {
9+
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html#API_ListObjects_Example_8
10+
const xml = `<?xml version='1.0' encoding='utf-8' ?>
11+
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
12+
<Name>example-bucket</Name>
13+
<Prefix>photos/2006/</Prefix>
14+
<Marker></Marker>
15+
<MaxKeys>1000</MaxKeys>
16+
<Delimiter>/</Delimiter>
17+
<IsTruncated>false</IsTruncated>
18+
<CommonPrefixes>
19+
<Prefix>photos/2006/February/</Prefix>
20+
</CommonPrefixes>
21+
<CommonPrefixes>
22+
<Prefix>photos/2006/January/</Prefix>
23+
</CommonPrefixes>
24+
</ListBucketResult>`;
25+
26+
assertEquals(bucket["parseListObjectResponseXml"](xml).commonPrefixes, [
27+
{ prefix: "photos/2006/February/" },
28+
{ prefix: "photos/2006/January/" },
29+
]);
30+
});
31+
32+
await t.step("commonPrefixes with entity escapes", () => {
33+
const xml = `<?xml version='1.0' encoding='utf-8' ?>
34+
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
35+
<Name>example-bucket</Name>
36+
<Prefix>photos/2006/</Prefix>
37+
<Marker></Marker>
38+
<MaxKeys>1000</MaxKeys>
39+
<Delimiter>/</Delimiter>
40+
<IsTruncated>false</IsTruncated>
41+
<CommonPrefixes>
42+
<Prefix>photos/2006/a&amp;b/</Prefix>
43+
</CommonPrefixes>
44+
</ListBucketResult>`;
45+
46+
assertEquals(bucket["parseListObjectResponseXml"](xml).commonPrefixes, [
47+
{ prefix: "photos/2006/a&b/" },
48+
]);
49+
});
50+
});
51+
});

src/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ export interface ListObjectsResponse {
243243
/**
244244
* All of the keys rolled up into a common prefix count as a single return when calculating the number of returns. A response can contain CommonPrefixes only if you specify a delimiter. CommonPrefixes contains all (if there are any) keys between Prefix and the next occurrence of the string specified by a delimiter. CommonPrefixes lists keys that act like subdirectories in the directory specified by Prefix. For example, if the prefix is notes/ and the delimiter is a slash (/) as in notes/summer/july, the common prefix is notes/summer/. All of the keys that roll up into a common prefix count as a single return when calculating the number of returns.
245245
*/
246-
commonPrefixes?: CommonPrefix[];
246+
commonPrefixes: CommonPrefix[];
247247
/**
248248
* Encoding type used by Amazon S3 to encode object key names in the XML response. If you specify the encoding-type request parameter, Amazon S3 includes this element in the response, and returns encoded key name values in the following response elements: Delimiter, Prefix, Key, and StartAfter.
249249
*/

0 commit comments

Comments
 (0)