Skip to content

Commit ae9d5e9

Browse files
committed
test(client-s3): requestChecksumCalculation and responseChecksumValidation
1 parent 2b17b51 commit ae9d5e9

File tree

1 file changed

+180
-138
lines changed

1 file changed

+180
-138
lines changed
Lines changed: 180 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { ChecksumAlgorithm, DEFAULT_CHECKSUM_ALGORITHM } from "@aws-sdk/middleware-flexible-checksums";
1+
import {
2+
ChecksumAlgorithm,
3+
DEFAULT_CHECKSUM_ALGORITHM,
4+
RequestChecksumCalculation,
5+
ResponseChecksumValidation,
6+
} from "@aws-sdk/middleware-flexible-checksums";
27
import { HttpRequest } from "@smithy/protocol-http";
38
import { BuildMiddleware } from "@smithy/types";
49
import { Readable } from "stream";
@@ -29,147 +34,184 @@ describe("Flexible Checksums", () => {
2934
];
3035

3136
describe("putObject", () => {
32-
testCases.forEach(([body, checksumAlgorithm, checksumValue]) => {
33-
const checksumHeader = `x-amz-checksum-${(checksumAlgorithm ?? DEFAULT_CHECKSUM_ALGORITHM).toLowerCase()}`;
34-
35-
describe(`sets ${checksumHeader}="${checksumValue}"" for checksum="${checksumAlgorithm}"`, () => {
36-
const getBodyAsReadableStream = (content: string) => {
37-
const readableStream = new Readable();
38-
const separator = " ";
39-
const wordsAsChunks = content.split(separator);
40-
wordsAsChunks.forEach((word, index) => {
41-
readableStream.push(word);
42-
if (index !== wordsAsChunks.length - 1) {
43-
readableStream.push(separator);
44-
}
45-
});
46-
readableStream.push(null);
47-
return readableStream;
48-
};
49-
50-
it(`when body is sent as a request`, async () => {
51-
const requestChecksumValidator: BuildMiddleware<any, any> = (next) => async (args) => {
52-
// middleware intercept the request and return it early
53-
const request = args.request as HttpRequest;
54-
const { headers } = request;
55-
expect(headers["x-amz-sdk-checksum-algorithm"]).to.equal(checksumAlgorithm ?? DEFAULT_CHECKSUM_ALGORITHM);
56-
expect(headers[checksumHeader]).to.equal(checksumValue);
57-
return { output: {} as any, response: {} as any };
58-
};
59-
60-
const client = new S3({
61-
region: "us-west-2",
62-
credentials: {
63-
accessKeyId: "CLIENT_TEST",
64-
secretAccessKey: "CLIENT_TEST",
65-
},
66-
});
67-
client.middlewareStack.addRelativeTo(requestChecksumValidator, {
68-
relation: "after",
69-
toMiddleware: "flexibleChecksumsMiddleware",
70-
});
71-
72-
return await client.putObject({
73-
Bucket: "bucket",
74-
Key: "key",
75-
Body: body,
76-
ChecksumAlgorithm: checksumAlgorithm as Algo,
77-
});
78-
});
79-
80-
it(`when body is sent as a stream`, async () => {
81-
const requestChecksumValidator: BuildMiddleware<any, any> = (next) => async (args) => {
82-
// middleware intercept the request and return it early
83-
const request = args.request as HttpRequest;
84-
const { headers, body } = request;
85-
expect(headers["content-length"]).to.be.undefined;
86-
expect(headers["content-encoding"]).to.equal("aws-chunked");
87-
expect(headers["transfer-encoding"]).to.equal("chunked");
88-
expect(headers["x-amz-content-sha256"]).to.equal("STREAMING-UNSIGNED-PAYLOAD-TRAILER");
89-
expect(headers["x-amz-trailer"]).to.equal(checksumHeader);
90-
body.on("data", (data: any) => {
91-
const stringValue = data.toString();
92-
if (stringValue.startsWith(checksumHeader)) {
93-
const receivedChecksum = stringValue.replace("\r\n", "").split(":")[1];
94-
expect(receivedChecksum).to.equal(checksumValue);
95-
}
37+
describe.each([undefined, RequestChecksumCalculation.WHEN_SUPPORTED, RequestChecksumCalculation.WHEN_REQUIRED])(
38+
`when requestChecksumCalculation='%s'`,
39+
(requestChecksumCalculation) => {
40+
describe.each(testCases)(
41+
`for body="%s" and checksumAlgorithm="%s", sets checksum="%s"`,
42+
(body, checksumAlgorithm, checksumValue) => {
43+
const checksumHeader = `x-amz-checksum-${(checksumAlgorithm ?? DEFAULT_CHECKSUM_ALGORITHM).toLowerCase()}`;
44+
const getBodyAsReadableStream = (content: string) => {
45+
const readableStream = new Readable();
46+
const separator = " ";
47+
const wordsAsChunks = content.split(separator);
48+
wordsAsChunks.forEach((word, index) => {
49+
readableStream.push(word);
50+
if (index !== wordsAsChunks.length - 1) {
51+
readableStream.push(separator);
52+
}
53+
});
54+
readableStream.push(null);
55+
return readableStream;
56+
};
57+
58+
it(`when body is sent as a request`, async () => {
59+
const requestChecksumValidator: BuildMiddleware<any, any> = (next) => async (args) => {
60+
// middleware intercept the request and return it early
61+
const request = args.request as HttpRequest;
62+
const { headers } = request;
63+
64+
// Headers are not set when checksumAlgorithm is not provided,
65+
// and requestChecksumCalculation is explicitly set to WHEN_SUPPORTED.
66+
if (
67+
checksumAlgorithm === undefined &&
68+
requestChecksumCalculation === RequestChecksumCalculation.WHEN_REQUIRED
69+
) {
70+
expect(headers["x-amz-sdk-checksum-algorithm"]).toBeUndefined();
71+
expect(headers[checksumHeader]).toBeUndefined();
72+
} else {
73+
expect(headers["x-amz-sdk-checksum-algorithm"]).to.equal(
74+
checksumAlgorithm ?? DEFAULT_CHECKSUM_ALGORITHM
75+
);
76+
expect(headers[checksumHeader]).to.equal(checksumValue);
77+
}
78+
79+
return { output: {} as any, response: {} as any };
80+
};
81+
82+
const client = new S3({
83+
region: "us-west-2",
84+
credentials: {
85+
accessKeyId: "CLIENT_TEST",
86+
secretAccessKey: "CLIENT_TEST",
87+
},
88+
requestChecksumCalculation,
89+
});
90+
client.middlewareStack.addRelativeTo(requestChecksumValidator, {
91+
relation: "after",
92+
toMiddleware: "flexibleChecksumsMiddleware",
93+
});
94+
95+
return await client.putObject({
96+
Bucket: "bucket",
97+
Key: "key",
98+
Body: body,
99+
ChecksumAlgorithm: checksumAlgorithm as Algo,
100+
});
101+
});
102+
103+
it(`when body is sent as a stream`, async () => {
104+
const requestChecksumValidator: BuildMiddleware<any, any> = (next) => async (args) => {
105+
// middleware intercept the request and return it early
106+
const request = args.request as HttpRequest;
107+
const { headers, body } = request;
108+
expect(headers["content-length"]).to.be.undefined;
109+
expect(headers["content-encoding"]).to.equal("aws-chunked");
110+
expect(headers["transfer-encoding"]).to.equal("chunked");
111+
expect(headers["x-amz-content-sha256"]).to.equal("STREAMING-UNSIGNED-PAYLOAD-TRAILER");
112+
expect(headers["x-amz-trailer"]).to.equal(checksumHeader);
113+
body.on("data", (data: any) => {
114+
const stringValue = data.toString();
115+
if (stringValue.startsWith(checksumHeader)) {
116+
const receivedChecksum = stringValue.replace("\r\n", "").split(":")[1];
117+
expect(receivedChecksum).to.equal(checksumValue);
118+
}
119+
});
120+
return { output: {} as any, response: {} as any };
121+
};
122+
123+
const client = new S3({
124+
region: "us-west-2",
125+
credentials: {
126+
accessKeyId: "CLIENT_TEST",
127+
secretAccessKey: "CLIENT_TEST",
128+
},
129+
});
130+
client.middlewareStack.addRelativeTo(requestChecksumValidator, {
131+
relation: "after",
132+
toMiddleware: "flexibleChecksumsMiddleware",
133+
});
134+
135+
const bodyStream = getBodyAsReadableStream(body);
136+
await client.putObject({
137+
Bucket: "bucket",
138+
Key: "key",
139+
Body: bodyStream,
140+
ChecksumAlgorithm: checksumAlgorithm as Algo,
141+
});
96142
});
97-
return { output: {} as any, response: {} as any };
98-
};
99-
100-
const client = new S3({
101-
region: "us-west-2",
102-
credentials: {
103-
accessKeyId: "CLIENT_TEST",
104-
secretAccessKey: "CLIENT_TEST",
105-
},
106-
});
107-
client.middlewareStack.addRelativeTo(requestChecksumValidator, {
108-
relation: "after",
109-
toMiddleware: "flexibleChecksumsMiddleware",
110-
});
111-
112-
const bodyStream = getBodyAsReadableStream(body);
113-
await client.putObject({
114-
Bucket: "bucket",
115-
Key: "key",
116-
Body: bodyStream,
117-
ChecksumAlgorithm: checksumAlgorithm as Algo,
118-
});
119-
});
120-
});
121-
});
143+
}
144+
);
145+
}
146+
);
122147
});
123148

124149
describe("getObject", async () => {
125-
testCases.forEach(([body, checksumAlgorithm, checksumValue]) => {
126-
const checksumHeader = `x-amz-checksum-${(checksumAlgorithm ?? DEFAULT_CHECKSUM_ALGORITHM).toLowerCase()}`;
127-
128-
it(`validates ${checksumHeader}="${checksumValue}"" set for checksum="${checksumAlgorithm}"`, async () => {
129-
const responseBody = new Readable();
130-
responseBody.push(body);
131-
responseBody.push(null);
132-
const responseChecksumValidator: BuildMiddleware<any, any> = (next, context) => async (args) => {
133-
expect(args.input.ChecksumMode).to.equal("ENABLED");
134-
const request = args.request as HttpRequest;
135-
return {
136-
output: {
137-
$metadata: { attempts: 0, httpStatusCode: 200 },
138-
request,
139-
context,
140-
Body: responseBody,
141-
} as any,
142-
response: {
143-
body: responseBody,
144-
headers: {
145-
[checksumHeader]: checksumValue,
150+
describe.each([undefined, ResponseChecksumValidation.WHEN_SUPPORTED, ResponseChecksumValidation.WHEN_REQUIRED])(
151+
`when responseChecksumValidation='%s'`,
152+
(responseChecksumValidation) => {
153+
it.each(testCases)(
154+
`for body="%s" and checksumAlgorithm="%s", validates ChecksumMode`,
155+
async (body, checksumAlgorithm, checksumValue) => {
156+
const checksumHeader = `x-amz-checksum-${(checksumAlgorithm ?? DEFAULT_CHECKSUM_ALGORITHM).toLowerCase()}`;
157+
158+
const responseBody = new Readable();
159+
responseBody.push(body);
160+
responseBody.push(null);
161+
const responseChecksumValidator: BuildMiddleware<any, any> = (next, context) => async (args) => {
162+
// ChecksumMode is not set when checksumAlgorithm is not provided,
163+
// and responseChecksumValidation is explicitly set to WHEN_SUPPORTED.
164+
if (
165+
checksumAlgorithm === undefined &&
166+
responseChecksumValidation === ResponseChecksumValidation.WHEN_REQUIRED
167+
) {
168+
expect(args.input.ChecksumMode).toBeUndefined();
169+
} else {
170+
expect(args.input.ChecksumMode).toEqual("ENABLED");
171+
}
172+
173+
const request = args.request as HttpRequest;
174+
return {
175+
output: {
176+
$metadata: { attempts: 0, httpStatusCode: 200 },
177+
request,
178+
context,
179+
Body: responseBody,
180+
} as any,
181+
response: {
182+
body: responseBody,
183+
headers: {
184+
[checksumHeader]: checksumValue,
185+
},
186+
} as any,
187+
};
188+
};
189+
190+
const client = new S3({
191+
region: "us-west-2",
192+
credentials: {
193+
accessKeyId: "CLIENT_TEST",
194+
secretAccessKey: "CLIENT_TEST",
146195
},
147-
} as any,
148-
};
149-
};
150-
151-
const client = new S3({
152-
region: "us-west-2",
153-
credentials: {
154-
accessKeyId: "CLIENT_TEST",
155-
secretAccessKey: "CLIENT_TEST",
156-
},
157-
});
158-
client.middlewareStack.addRelativeTo(responseChecksumValidator, {
159-
relation: "after",
160-
toMiddleware: "flexibleChecksumsMiddleware",
161-
});
162-
163-
const { Body } = await client.getObject({
164-
Bucket: "bucket",
165-
Key: "key",
166-
// Do not pass ChecksumMode if algorithm is not explicitly defined. It'll be set by SDK.
167-
ChecksumMode: checksumAlgorithm ? "ENABLED" : undefined,
168-
});
169-
(Body as Readable).on("data", (chunk) => {
170-
expect(chunk.toString()).to.equal(body);
171-
});
172-
});
173-
});
196+
responseChecksumValidation,
197+
});
198+
client.middlewareStack.addRelativeTo(responseChecksumValidator, {
199+
relation: "after",
200+
toMiddleware: "flexibleChecksumsMiddleware",
201+
});
202+
203+
const { Body } = await client.getObject({
204+
Bucket: "bucket",
205+
Key: "key",
206+
// Do not pass ChecksumMode if algorithm is not explicitly defined. It'll be set by SDK.
207+
ChecksumMode: checksumAlgorithm ? "ENABLED" : undefined,
208+
});
209+
(Body as Readable).on("data", (chunk) => {
210+
expect(chunk.toString()).to.equal(body);
211+
});
212+
}
213+
);
214+
}
215+
);
174216
});
175217
});

0 commit comments

Comments
 (0)