diff --git a/packages/middleware-sdk-transcribe-streaming/src/signer.spec.ts b/packages/middleware-sdk-transcribe-streaming/src/signer.spec.ts new file mode 100644 index 0000000000000..e8d9c5acbf574 --- /dev/null +++ b/packages/middleware-sdk-transcribe-streaming/src/signer.spec.ts @@ -0,0 +1,42 @@ +import { HttpRequest } from "@aws-sdk/protocol-http"; +import { SignatureV4 } from "./signer"; +describe("transcribe streaming", () => { + describe("WebSocket request signer", () => { + it("should invoke base SigV4 signer correctly", async () => { + expect.assertions(5); + const toSign = new HttpRequest({ + headers: { + "x-amz-foo": "foo", + bar: "bar", + "amz-sdk-invocation-id": "123", + "amz-sdk-request": "attempt=1", + host: "aws.amazon.com" + }, + body: "hello world", + query: { + prop1: "A", + prop2: "B" + } + }); + const mockBaseSigner = { + presign: jest + .fn() + .mockImplementation(request => Promise.resolve(request)) + }; + const signer = new SignatureV4({ signer: mockBaseSigner as any }); + const signed = await signer.sign(toSign); + expect(toSign).toMatchObject(signed); + expect(mockBaseSigner.presign).toBeCalled(); + // The request's body should not be presigned + expect(mockBaseSigner.presign.mock.calls[0][0].body).toEqual(""); + expect( + mockBaseSigner.presign.mock.calls[0][1]!.unsignableHeaders + ).toBeDefined(); + const unsignableHeaders: Set = mockBaseSigner.presign.mock + .calls[0][1]!.unsignableHeaders; + expect([...unsignableHeaders.entries()].map(([value]) => value)).toEqual( + Object.keys(toSign.headers).filter(a => a !== "host") + ); + }); + }); +}); diff --git a/packages/middleware-sdk-transcribe-streaming/src/signer.ts b/packages/middleware-sdk-transcribe-streaming/src/signer.ts index ea9849d15a4bd..132b6917f1460 100644 --- a/packages/middleware-sdk-transcribe-streaming/src/signer.ts +++ b/packages/middleware-sdk-transcribe-streaming/src/signer.ts @@ -27,10 +27,20 @@ export class SignatureV4 implements RequestSigner, RequestPresigner { ): Promise { if (HttpRequest.isInstance(toSign)) { // Presign the endpoint url with empty body, otherwise - // the payload hash would be UNSINGED_PAYLOAD - const signedRequest = await this.signer.presign({ ...toSign, body: "" }, { - expiresIn: 5 * 60 // presigned url must be expired within 5 mins - } as any); + // the payload hash would be UNSINGED-PAYLOAD + const signedRequest = await this.signer.presign( + { ...toSign, body: "" }, + { + // presigned url must be expired within 5 mins. + expiresIn: 5 * 60, + // Not to sign headers. Transcribe-streaming WebSocket + // request omits headers except for required 'host' header. If we sign + // the other headers, the signature could be mismatch. + unsignableHeaders: new Set( + Object.keys(toSign.headers).filter(header => header !== "host") + ) + } + ); return { ...signedRequest, body: toSign.body