diff --git a/packages/s3-request-presigner/src/getSignedUrl.spec.ts b/packages/s3-request-presigner/src/getSignedUrl.spec.ts index 3b5aafcf4804..c0090e91d4df 100644 --- a/packages/s3-request-presigner/src/getSignedUrl.spec.ts +++ b/packages/s3-request-presigner/src/getSignedUrl.spec.ts @@ -99,4 +99,16 @@ describe("getSignedUrl", () => { expect(mockPresign).toBeCalled(); expect(mockPresign.mock.calls[0][1]).toMatchObject(options); }); + + it("should not throw if it's called concurrently", async () => { + const mockPresigned = "a presigned url"; + mockPresign.mockReturnValue(mockPresigned); + const client = new S3Client(clientParams); + const command = new GetObjectCommand({ + Bucket: "Bucket", + Key: "Key", + }); + const commands = [command, command]; + return expect(Promise.all(commands.map((command) => getSignedUrl(client, command)))).resolves.toBeInstanceOf(Array); + }); }); diff --git a/packages/s3-request-presigner/src/getSignedUrl.ts b/packages/s3-request-presigner/src/getSignedUrl.ts index 3d3c22305df0..a67a9665f352 100644 --- a/packages/s3-request-presigner/src/getSignedUrl.ts +++ b/packages/s3-request-presigner/src/getSignedUrl.ts @@ -40,11 +40,20 @@ export const getSignedUrl = async < }, } as any; }; - client.middlewareStack.addRelativeTo(presignInterceptMiddleware, { - name: "presignInterceptMiddleware", - relation: "before", - toMiddleware: "awsAuthMiddleware", - }); + const middlewareName = "presignInterceptMiddleware"; + try { + client.middlewareStack.addRelativeTo(presignInterceptMiddleware, { + name: middlewareName, + relation: "before", + toMiddleware: "awsAuthMiddleware", + }); + } catch (e) { + if (e.message!.includes(`Duplicated middleware name '${middlewareName}'`)) { + // Swallow if the interceptor is already added. See https://github.com/aws/aws-sdk-js-v3/issues/1857 + } else { + throw e; + } + } let presigned: HttpRequest; try { @@ -52,7 +61,7 @@ export const getSignedUrl = async < //@ts-ignore the output is faked, so it's not actually OutputType presigned = output.presigned; } finally { - client.middlewareStack.remove("presignInterceptMiddleware"); + client.middlewareStack.remove(middlewareName); } return formatUrl(presigned);