From 43f401b5a473449c0aa892e7cf7df9e86befffee Mon Sep 17 00:00:00 2001 From: George Fu Date: Tue, 2 Apr 2024 12:16:51 -0400 Subject: [PATCH] feat(client-sqs): add option to prevent md5 computation (#5953) * feat(client-sqs): add option to prevent md5 computation * feat(client-sqs): handle md5=false in sqs middleware --- UPGRADING.md | 27 ++++++++++++++----- clients/client-sqs/src/SQSClient.ts | 5 ++-- .../typescript/codegen/AddSqsDependency.java | 5 ++-- .../middleware-sdk-sqs/src/configurations.ts | 2 +- .../src/middleware-sdk-sqs.integ.spec.ts | 3 +-- .../middleware-sdk-sqs/src/receive-message.ts | 3 +++ .../src/receive-messages.spec.ts | 19 +++++++++++++ .../src/send-message-batch.ts | 3 +++ .../middleware-sdk-sqs/src/send-message.ts | 3 +++ 9 files changed, 55 insertions(+), 15 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index f4cd0e4b92a4..1e317914dd4f 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -573,10 +573,10 @@ In v3, the similar utility function is available in [`@aws-sdk/polly-request-pre ### Amazon S3 -Streaming vs. buffered responses: the JSv3 SDK prefers not to buffer potentially large responses. This is commonly encountered in S3's GetObject operation, which returned a `Buffer` in JSv2, but +Streaming vs. buffered responses: the JSv3 SDK prefers not to buffer potentially large responses. This is commonly encountered in S3's GetObject operation, which returned a `Buffer` in JSv2, but returns a `Stream` in JSv3. -For Node.js, you must consume the stream or garbage collect the client or its request handler to keep the connections open to new traffic by freeing sockets. +For Node.js, you must consume the stream or garbage collect the client or its request handler to keep the connections open to new traffic by freeing sockets. ```ts // v2 @@ -642,7 +642,22 @@ const region = "..."; ### Amazon SQS -When using a custom `QueueUrl` in SQS operations that have this as an input parameter, in JSv2 +#### MD5 Checksum + +To skip computation of MD5 checksums of message bodies, set `md5=false` on the configuration object. +Otherwise, by default the SDK will calculate the checksum for sending messages, as well as validating the checksum +for retrieved messages. + +```ts +// Example: skip md5 checksum in SQS. +import { SQS } from "@aws-sdk/client-sqs"; + +new SQS({ + md5: false, // Note: only available in v3.547.0 and higher. +}); +``` + +When using a custom `QueueUrl` in SQS operations that have this as an input parameter, in JSv2 it was possible to supply a custom `QueueUrl` which would override the SQS Client's default endpoint. #### Mutli-region messages @@ -669,11 +684,11 @@ for (const { region, url } of queues) { }; await sqsClients[region].sendMessage(params); } -``` +``` #### Custom endpoint -In JSv3, when using a custom endpoint, i.e. one that differs from the default public SQS endpoints, you +In JSv3, when using a custom endpoint, i.e. one that differs from the default public SQS endpoints, you should always set the endpoint on the SQS Client as well as the `QueueUrl` field. ```ts @@ -703,6 +718,6 @@ const sqs = new SQS({ await sqs.sendMessage({ QueueUrl: "https://sqs.us-west-2.amazonaws.com/1234567/MyQueue", - Message: "hello" + Message: "hello", }); ``` diff --git a/clients/client-sqs/src/SQSClient.ts b/clients/client-sqs/src/SQSClient.ts index 6dcee104f188..3fc37063e1f2 100644 --- a/clients/client-sqs/src/SQSClient.ts +++ b/clients/client-sqs/src/SQSClient.ts @@ -257,10 +257,9 @@ export interface ClientDefaults extends Partial<__SmithyConfiguration<__HttpHand /** * A constructor for a class implementing the {@link __Checksum} interface - * that computes MD5 hashes. - * @internal + * that computes MD5 hashes, or false to prevent MD5 computation. */ - md5?: __ChecksumConstructor | __HashConstructor; + md5?: __ChecksumConstructor | __HashConstructor | false; /** * The provider populating default tracking information to be sent with `user-agent`, `x-amz-user-agent` header diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddSqsDependency.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddSqsDependency.java index 13ced35599df..97f9ebd4c729 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddSqsDependency.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddSqsDependency.java @@ -87,9 +87,8 @@ public void addConfigInterfaceFields( writer.addImport("Checksum", "__Checksum", TypeScriptDependency.SMITHY_TYPES); writer.addImport("ChecksumConstructor", "__ChecksumConstructor", TypeScriptDependency.SMITHY_TYPES); writer.writeDocs("A constructor for a class implementing the {@link __Checksum} interface \n" - + "that computes MD5 hashes.\n" - + "@internal"); - writer.write("md5?: __ChecksumConstructor | __HashConstructor;\n"); + + "that computes MD5 hashes, or false to prevent MD5 computation."); + writer.write("md5?: __ChecksumConstructor | __HashConstructor | false;\n"); } @Override diff --git a/packages/middleware-sdk-sqs/src/configurations.ts b/packages/middleware-sdk-sqs/src/configurations.ts index e24e8197c79c..f06e1971c0e0 100644 --- a/packages/middleware-sdk-sqs/src/configurations.ts +++ b/packages/middleware-sdk-sqs/src/configurations.ts @@ -1,5 +1,5 @@ import { ChecksumConstructor, HashConstructor } from "@smithy/types"; export interface PreviouslyResolved { - md5: ChecksumConstructor | HashConstructor; + md5: ChecksumConstructor | HashConstructor | false; } diff --git a/packages/middleware-sdk-sqs/src/middleware-sdk-sqs.integ.spec.ts b/packages/middleware-sdk-sqs/src/middleware-sdk-sqs.integ.spec.ts index f0c38a9aa811..4f9d437f3a71 100644 --- a/packages/middleware-sdk-sqs/src/middleware-sdk-sqs.integ.spec.ts +++ b/packages/middleware-sdk-sqs/src/middleware-sdk-sqs.integ.spec.ts @@ -103,8 +103,7 @@ const handlerResponse = (body: string) => { }; describe("middleware-sdk-sqs", () => { - // TODO: check in CI - xdescribe(SQS.name + ` w/ useAwsQuery: ${useAwsQuery}`, () => { + describe(SQS.name + ` w/ useAwsQuery: ${useAwsQuery}`, () => { describe("correct md5 hashes", () => { beforeEach(() => { hashError = ""; diff --git a/packages/middleware-sdk-sqs/src/receive-message.ts b/packages/middleware-sdk-sqs/src/receive-message.ts index 0139cfed6356..3c82c394d1b4 100644 --- a/packages/middleware-sdk-sqs/src/receive-message.ts +++ b/packages/middleware-sdk-sqs/src/receive-message.ts @@ -26,6 +26,9 @@ export function receiveMessageMiddleware(options: PreviouslyResolved): Initializ return (next: InitializeHandler): InitializeHandler => async (args: InitializeHandlerArguments): Promise> => { const resp = await next({ ...args }); + if (options.md5 === false) { + return resp; + } const output = resp.output as unknown as ReceiveMessageResult; const messageIds = []; if (output.Messages !== undefined) { diff --git a/packages/middleware-sdk-sqs/src/receive-messages.spec.ts b/packages/middleware-sdk-sqs/src/receive-messages.spec.ts index 1414f0ae81a0..1d185cfaad06 100644 --- a/packages/middleware-sdk-sqs/src/receive-messages.spec.ts +++ b/packages/middleware-sdk-sqs/src/receive-messages.spec.ts @@ -69,4 +69,23 @@ describe("receiveMessageMiddleware", () => { expect(mockHashUpdate.mock.calls.length).toBe(2); expect(mockHashDigest.mock.calls.length).toBe(2); }); + + it("ignores checksum if md5=false in config", async () => { + const next = jest.fn().mockReturnValue({ + output: { + Messages: [ + { Body: "foo", MD5OfBody: "XXYYZZ", MessageId: "fooMessage" }, + { Body: "bar", MD5OfBody: "XXYYZZ", MessageId: "barMessage" }, + ], + }, + }); + const handler = receiveMessageMiddleware({ + md5: false, + })(next, {} as any); + + await handler({ input: {} }); + + expect(mockHashUpdate.mock.calls.length).toBe(0); + expect(mockHashDigest.mock.calls.length).toBe(0); + }); }); diff --git a/packages/middleware-sdk-sqs/src/send-message-batch.ts b/packages/middleware-sdk-sqs/src/send-message-batch.ts index 31fbaed3c8f9..0f18bb9fb906 100644 --- a/packages/middleware-sdk-sqs/src/send-message-batch.ts +++ b/packages/middleware-sdk-sqs/src/send-message-batch.ts @@ -27,6 +27,9 @@ export const sendMessageBatchMiddleware = (next: InitializeHandler): InitializeHandler => async (args: InitializeHandlerArguments): Promise> => { const resp = await next({ ...args }); + if (options.md5 === false) { + return resp; + } const output = resp.output as unknown as SendMessageBatchResult; const messageIds = []; const entries: Record = {}; diff --git a/packages/middleware-sdk-sqs/src/send-message.ts b/packages/middleware-sdk-sqs/src/send-message.ts index e62ae5fb1aa8..86d6c6e77871 100644 --- a/packages/middleware-sdk-sqs/src/send-message.ts +++ b/packages/middleware-sdk-sqs/src/send-message.ts @@ -21,6 +21,9 @@ export const sendMessageMiddleware = (next: InitializeHandler): InitializeHandler => async (args: InitializeHandlerArguments): Promise> => { const resp = await next({ ...args }); + if (options.md5 === false) { + return resp; + } const output = resp.output as SendMessageResult; const hash = new options.md5(); hash.update(toUint8Array(args.input.MessageBody || ""));