Skip to content

Commit 7dbc1c9

Browse files
authored
fix(middleware-flexible-checksums): skip checksum validation if CRC64NVME dependency is absent (#6835)
1 parent c3f3d0a commit 7dbc1c9

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

packages/middleware-flexible-checksums/src/flexibleChecksumsResponseMiddleware.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export const flexibleChecksumsResponseMiddleware =
9494
await validateChecksumFromResponse(result.response as HttpResponse, {
9595
config,
9696
responseAlgorithms,
97+
logger: context.logger,
9798
});
9899

99100
if (isStreamingBody && collectedStream) {

packages/middleware-flexible-checksums/src/validateChecksumFromResponse.spec.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { HttpResponse } from "@smithy/protocol-http";
2+
import { Logger } from "@smithy/types";
23
import { createChecksumStream } from "@smithy/util-stream";
34
import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest";
45

@@ -32,11 +33,13 @@ describe(validateChecksumFromResponse.name, () => {
3233
} as HttpResponse;
3334

3435
const mockChecksum = "mockChecksum";
35-
const mockResponseAlgorithms = [ChecksumAlgorithm.CRC32, ChecksumAlgorithm.CRC32C];
36+
const mockResponseAlgorithms = [ChecksumAlgorithm.CRC32, ChecksumAlgorithm.CRC32C, ChecksumAlgorithm.CRC64NVME];
37+
const mockLogger = { warn: vi.fn() } as unknown as Logger;
3638

3739
const mockOptions = {
3840
config: mockConfig,
3941
responseAlgorithms: mockResponseAlgorithms,
42+
logger: mockLogger,
4043
};
4144

4245
const mockChecksumAlgorithmFn = vi.fn();
@@ -66,7 +69,6 @@ describe(validateChecksumFromResponse.name, () => {
6669

6770
describe("skip validation", () => {
6871
afterEach(() => {
69-
expect(selectChecksumAlgorithmFunction).not.toHaveBeenCalled();
7072
expect(getChecksum).not.toHaveBeenCalled();
7173
});
7274

@@ -75,19 +77,38 @@ describe(validateChecksumFromResponse.name, () => {
7577
await validateChecksumFromResponse(mockResponse, { ...mockOptions, responseAlgorithms: emptyAlgorithmsList });
7678
expect(getChecksumAlgorithmListForResponse).toHaveBeenCalledWith(emptyAlgorithmsList);
7779
expect(getChecksumLocationName).not.toHaveBeenCalled();
80+
expect(selectChecksumAlgorithmFunction).not.toHaveBeenCalled();
7881
});
7982

8083
it("if updated algorithm list from response is empty", async () => {
8184
vi.mocked(getChecksumAlgorithmListForResponse).mockImplementation(() => []);
8285
await validateChecksumFromResponse(mockResponse, mockOptions);
8386
expect(getChecksumAlgorithmListForResponse).toHaveBeenCalledWith(mockResponseAlgorithms);
8487
expect(getChecksumLocationName).not.toHaveBeenCalled();
88+
expect(selectChecksumAlgorithmFunction).not.toHaveBeenCalled();
8589
});
8690

8791
it("if checksum is not present in header", async () => {
8892
await validateChecksumFromResponse(mockResponse, mockOptions);
8993
expect(getChecksumAlgorithmListForResponse).toHaveBeenCalledWith(mockResponseAlgorithms);
9094
expect(getChecksumLocationName).toHaveBeenCalledTimes(mockResponseAlgorithms.length);
95+
expect(selectChecksumAlgorithmFunction).not.toHaveBeenCalled();
96+
});
97+
98+
it(`if checksum algorithm is ${ChecksumAlgorithm.CRC64NVME} and dependency is not available`, async () => {
99+
const dependencyErrorMsg = "Dependency not available";
100+
vi.mocked(selectChecksumAlgorithmFunction).mockImplementation(() => {
101+
throw new Error(dependencyErrorMsg);
102+
});
103+
const responseWithChecksum = getMockResponseWithHeader(ChecksumAlgorithm.CRC64NVME, mockChecksum);
104+
await validateChecksumFromResponse(responseWithChecksum, mockOptions);
105+
expect(getChecksumAlgorithmListForResponse).toHaveBeenCalledWith(mockResponseAlgorithms);
106+
expect(getChecksumLocationName).toHaveBeenCalledTimes(mockResponseAlgorithms.length);
107+
expect(selectChecksumAlgorithmFunction).toHaveBeenCalledTimes(1);
108+
expect(mockLogger.warn).toHaveBeenCalledTimes(1);
109+
expect(mockLogger.warn).toHaveBeenCalledWith(
110+
`Skipping ${ChecksumAlgorithm.CRC64NVME} checksum validation: ${dependencyErrorMsg}`
111+
);
91112
});
92113
});
93114

@@ -134,6 +155,17 @@ describe(validateChecksumFromResponse.name, () => {
134155
expect(getChecksumLocationName).toHaveBeenNthCalledWith(2, mockResponseAlgorithms[1]);
135156
validateCalls(isStream, mockResponseAlgorithms[1]);
136157
});
158+
159+
it.each([false, true])("when checksum is populated for third algorithm when streaming: %s", async (isStream) => {
160+
vi.mocked(isStreaming).mockReturnValue(isStream);
161+
const responseWithChecksum = getMockResponseWithHeader(mockResponseAlgorithms[2], mockChecksum);
162+
await validateChecksumFromResponse(responseWithChecksum, mockOptions);
163+
expect(getChecksumLocationName).toHaveBeenCalledTimes(3);
164+
expect(getChecksumLocationName).toHaveBeenNthCalledWith(1, mockResponseAlgorithms[0]);
165+
expect(getChecksumLocationName).toHaveBeenNthCalledWith(2, mockResponseAlgorithms[1]);
166+
expect(getChecksumLocationName).toHaveBeenNthCalledWith(3, mockResponseAlgorithms[2]);
167+
validateCalls(isStream, mockResponseAlgorithms[2]);
168+
});
137169
});
138170

139171
it("throw error if checksum value is not accurate when not streaming", async () => {

packages/middleware-flexible-checksums/src/validateChecksumFromResponse.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { HttpResponse } from "@smithy/protocol-http";
2-
import { Checksum } from "@smithy/types";
2+
import { Checksum, ChecksumConstructor, HashConstructor, Logger } from "@smithy/types";
33
import { createChecksumStream } from "@smithy/util-stream";
44

55
import { PreviouslyResolved } from "./configuration";
@@ -18,11 +18,13 @@ export interface ValidateChecksumFromResponseOptions {
1818
* returned in the HTTP response.
1919
*/
2020
responseAlgorithms?: string[];
21+
22+
logger?: Logger;
2123
}
2224

2325
export const validateChecksumFromResponse = async (
2426
response: HttpResponse,
25-
{ config, responseAlgorithms }: ValidateChecksumFromResponseOptions
27+
{ config, responseAlgorithms, logger }: ValidateChecksumFromResponseOptions
2628
) => {
2729
// Verify checksum in response header.
2830
const checksumAlgorithms = getChecksumAlgorithmListForResponse(responseAlgorithms);
@@ -31,7 +33,17 @@ export const validateChecksumFromResponse = async (
3133
const responseHeader = getChecksumLocationName(algorithm);
3234
const checksumFromResponse = responseHeaders[responseHeader];
3335
if (checksumFromResponse) {
34-
const checksumAlgorithmFn = selectChecksumAlgorithmFunction(algorithm as ChecksumAlgorithm, config);
36+
let checksumAlgorithmFn: ChecksumConstructor | HashConstructor;
37+
try {
38+
checksumAlgorithmFn = selectChecksumAlgorithmFunction(algorithm as ChecksumAlgorithm, config);
39+
} catch (error) {
40+
if (algorithm === ChecksumAlgorithm.CRC64NVME) {
41+
logger?.warn(`Skipping ${ChecksumAlgorithm.CRC64NVME} checksum validation: ${error.message}`);
42+
continue;
43+
}
44+
throw error;
45+
}
46+
3547
const { base64Encoder } = config;
3648

3749
if (isStreaming(responseBody)) {

0 commit comments

Comments
 (0)