From e72b2ad5d2bb02d34fd909f52311f77e96c76151 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 11 Sep 2024 20:25:07 +0200 Subject: [PATCH 1/5] chore(commons): set AWS_SDK_UA_APP_ID --- packages/commons/src/awsSdkUtils.ts | 18 ++++- packages/commons/src/index.ts | 4 +- .../commons/tests/unit/awsSdkUtils.test.ts | 70 ++++++++++++++++++- 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/packages/commons/src/awsSdkUtils.ts b/packages/commons/src/awsSdkUtils.ts index df922f9e27..5eabe7f396 100644 --- a/packages/commons/src/awsSdkUtils.ts +++ b/packages/commons/src/awsSdkUtils.ts @@ -47,9 +47,23 @@ const isSdkClient = (client: unknown): client is SdkClient => const customUserAgentMiddleware = (feature: string) => { return (next: (arg0: T) => Promise) => async (args: T) => { - const powertoolsUserAgent = `PT/${feature}/${PT_VERSION} PTEnv/${EXEC_ENV}`; + const existingUserAgent = args.request.headers['user-agent'] || ''; + if (existingUserAgent.includes('PT/NO-OP')) { + const featureSpecificUserAgent = existingUserAgent.replace( + 'PT/NO-OP', + `PT/${feature}/${PT_VERSION} PTEnv/${EXEC_ENV}` + ); + + args.request.headers['user-agent'] = featureSpecificUserAgent; + return await next(args); + } + if (existingUserAgent.includes('PT/')) { + return await next(args); + } args.request.headers['user-agent'] = - `${args.request.headers['user-agent']} ${powertoolsUserAgent}`; + existingUserAgent === '' + ? `PT/${feature}/${PT_VERSION} PTEnv/${EXEC_ENV}` + : `${existingUserAgent} PT/${feature}/${PT_VERSION} PTEnv/${EXEC_ENV}`; return await next(args); }; diff --git a/packages/commons/src/index.ts b/packages/commons/src/index.ts index 591ad8ccff..c49b7714c6 100644 --- a/packages/commons/src/index.ts +++ b/packages/commons/src/index.ts @@ -1,3 +1,6 @@ +import { PT_VERSION } from './version.js'; +process.env.AWS_SDK_UA_APP_ID = `PT/NO-OP/${PT_VERSION}`; +export { PT_VERSION } from './version.js'; export { isRecord, isString, @@ -19,4 +22,3 @@ export { METRICS_KEY, IDEMPOTENCY_KEY, } from './middleware/constants.js'; -export { PT_VERSION } from './version.js'; diff --git a/packages/commons/tests/unit/awsSdkUtils.test.ts b/packages/commons/tests/unit/awsSdkUtils.test.ts index 907409b25d..8a7632d35f 100644 --- a/packages/commons/tests/unit/awsSdkUtils.test.ts +++ b/packages/commons/tests/unit/awsSdkUtils.test.ts @@ -96,7 +96,31 @@ describe('Helpers: awsSdk', () => { expect(middleware).toBeInstanceOf(Function); }); - it('adds the Powertools UA to the request headers', async () => { + it('adds the Powertools UA to the request headers when no user agent is present', async () => { + // Prepare + const feature = 'my-feature'; + const middleware = customUserAgentMiddleware(feature); + const next = jest.fn(); + const args = { + request: { + headers: {}, + }, + } as { + request: { + headers: Record; + }; + }; + + // Act + await middleware(next)(args); + + // Assess + expect(args.request.headers['user-agent']).toEqual( + `PT/my-feature/${version} PTEnv/NA` + ); + }); + + it('adds the Powertools UA to the request headers when no Powertools UA is present', async () => { // Prepare const feature = 'my-feature'; const middleware = customUserAgentMiddleware(feature); @@ -117,6 +141,50 @@ describe('Helpers: awsSdk', () => { `foo PT/my-feature/${version} PTEnv/NA` ); }); + + it('replaces the no-op Powertools UA with the the feature-specific one', async () => { + // Prepare + const feature = 'my-feature'; + const middleware = customUserAgentMiddleware(feature); + const next = jest.fn(); + const args = { + request: { + headers: { + 'user-agent': 'PT/NO-OP', + }, + }, + }; + + // Act + await middleware(next)(args); + + // Assess + expect(args.request.headers['user-agent']).toEqual( + `PT/my-feature/${version} PTEnv/NA` + ); + }); + + it('does not add the Powertools feature-specific UA if it is already present', async () => { + // Prepare + const feature = 'my-feature'; + const middleware = customUserAgentMiddleware(feature); + const next = jest.fn(); + const args = { + request: { + headers: { + 'user-agent': 'PT/other-feature/1.0 PTEnv/NA', + }, + }, + }; + + // Act + await middleware(next)(args); + + // Assess + expect(args.request.headers['user-agent']).toEqual( + 'PT/other-feature/1.0 PTEnv/NA' + ); + }); }); describe('Function: isSdkClient', () => { From cccf4995bf0881b054bb1f29f586f4724b3ee02e Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Mon, 24 Feb 2025 15:56:16 +0100 Subject: [PATCH 2/5] test: update unit tests --- packages/commons/tests/unit/awsSdkUtils.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/commons/tests/unit/awsSdkUtils.test.ts b/packages/commons/tests/unit/awsSdkUtils.test.ts index 8a7632d35f..497ca6641b 100644 --- a/packages/commons/tests/unit/awsSdkUtils.test.ts +++ b/packages/commons/tests/unit/awsSdkUtils.test.ts @@ -100,7 +100,7 @@ describe('Helpers: awsSdk', () => { // Prepare const feature = 'my-feature'; const middleware = customUserAgentMiddleware(feature); - const next = jest.fn(); + const next = vi.fn(); const args = { request: { headers: {}, @@ -146,7 +146,7 @@ describe('Helpers: awsSdk', () => { // Prepare const feature = 'my-feature'; const middleware = customUserAgentMiddleware(feature); - const next = jest.fn(); + const next = vi.fn(); const args = { request: { headers: { @@ -168,7 +168,7 @@ describe('Helpers: awsSdk', () => { // Prepare const feature = 'my-feature'; const middleware = customUserAgentMiddleware(feature); - const next = jest.fn(); + const next = vi.fn(); const args = { request: { headers: { From f1dd0c4736da1915ba67b514591cea652556ac66 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Mon, 24 Feb 2025 16:53:32 +0100 Subject: [PATCH 3/5] chore: set ua app id env only when not present --- packages/commons/src/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/commons/src/index.ts b/packages/commons/src/index.ts index c49b7714c6..03b21e2ef7 100644 --- a/packages/commons/src/index.ts +++ b/packages/commons/src/index.ts @@ -1,5 +1,7 @@ import { PT_VERSION } from './version.js'; -process.env.AWS_SDK_UA_APP_ID = `PT/NO-OP/${PT_VERSION}`; +if (!process.env.AWS_SDK_UA_APP_ID) { + process.env.AWS_SDK_UA_APP_ID = `PT/NO-OP/${PT_VERSION}`; +} export { PT_VERSION } from './version.js'; export { isRecord, From 421a01e13973a0ae7d7bf2016aaa5b7c24204bfb Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Mon, 24 Feb 2025 17:05:11 +0100 Subject: [PATCH 4/5] test: remove duplication --- .../commons/tests/unit/awsSdkUtils.test.ts | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/packages/commons/tests/unit/awsSdkUtils.test.ts b/packages/commons/tests/unit/awsSdkUtils.test.ts index 497ca6641b..a441a4e1df 100644 --- a/packages/commons/tests/unit/awsSdkUtils.test.ts +++ b/packages/commons/tests/unit/awsSdkUtils.test.ts @@ -96,11 +96,11 @@ describe('Helpers: awsSdk', () => { expect(middleware).toBeInstanceOf(Function); }); + const feature = 'my-feature'; + const middleware = customUserAgentMiddleware(feature); + it('adds the Powertools UA to the request headers when no user agent is present', async () => { // Prepare - const feature = 'my-feature'; - const middleware = customUserAgentMiddleware(feature); - const next = vi.fn(); const args = { request: { headers: {}, @@ -112,7 +112,7 @@ describe('Helpers: awsSdk', () => { }; // Act - await middleware(next)(args); + await middleware(vi.fn())(args); // Assess expect(args.request.headers['user-agent']).toEqual( @@ -122,9 +122,6 @@ describe('Helpers: awsSdk', () => { it('adds the Powertools UA to the request headers when no Powertools UA is present', async () => { // Prepare - const feature = 'my-feature'; - const middleware = customUserAgentMiddleware(feature); - const next = vi.fn(); const args = { request: { headers: { @@ -134,7 +131,7 @@ describe('Helpers: awsSdk', () => { }; // Act - await middleware(next)(args); + await middleware(vi.fn())(args); // Assess expect(args.request.headers['user-agent']).toEqual( @@ -144,9 +141,6 @@ describe('Helpers: awsSdk', () => { it('replaces the no-op Powertools UA with the the feature-specific one', async () => { // Prepare - const feature = 'my-feature'; - const middleware = customUserAgentMiddleware(feature); - const next = vi.fn(); const args = { request: { headers: { @@ -156,7 +150,7 @@ describe('Helpers: awsSdk', () => { }; // Act - await middleware(next)(args); + await middleware(vi.fn())(args); // Assess expect(args.request.headers['user-agent']).toEqual( @@ -166,9 +160,6 @@ describe('Helpers: awsSdk', () => { it('does not add the Powertools feature-specific UA if it is already present', async () => { // Prepare - const feature = 'my-feature'; - const middleware = customUserAgentMiddleware(feature); - const next = vi.fn(); const args = { request: { headers: { @@ -178,7 +169,7 @@ describe('Helpers: awsSdk', () => { }; // Act - await middleware(next)(args); + await middleware(vi.fn())(args); // Assess expect(args.request.headers['user-agent']).toEqual( From 66cb2c0339e7f9edde496ea77065dd5ab4966d7e Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Mon, 24 Feb 2025 17:12:06 +0100 Subject: [PATCH 5/5] test: remove duplication --- .../commons/tests/unit/awsSdkUtils.test.ts | 90 ++++++------------- 1 file changed, 27 insertions(+), 63 deletions(-) diff --git a/packages/commons/tests/unit/awsSdkUtils.test.ts b/packages/commons/tests/unit/awsSdkUtils.test.ts index a441a4e1df..c8f233e355 100644 --- a/packages/commons/tests/unit/awsSdkUtils.test.ts +++ b/packages/commons/tests/unit/awsSdkUtils.test.ts @@ -99,72 +99,38 @@ describe('Helpers: awsSdk', () => { const feature = 'my-feature'; const middleware = customUserAgentMiddleware(feature); - it('adds the Powertools UA to the request headers when no user agent is present', async () => { - // Prepare - const args = { - request: { - headers: {}, + it.each([ + { + case: 'adds the feature-specific UA when none is present', + headers: {}, + expected: `PT/my-feature/${version} PTEnv/NA`, + }, + { + case: 'concatenates the ua to existing ones', + headers: { + 'user-agent': 'foo', }, - } as { - request: { - headers: Record; - }; - }; - - // Act - await middleware(vi.fn())(args); - - // Assess - expect(args.request.headers['user-agent']).toEqual( - `PT/my-feature/${version} PTEnv/NA` - ); - }); - - it('adds the Powertools UA to the request headers when no Powertools UA is present', async () => { - // Prepare - const args = { - request: { - headers: { - 'user-agent': 'foo', - }, + expected: `foo PT/my-feature/${version} PTEnv/NA`, + }, + { + case: 'replaces no-op UA with the feature-specific one', + headers: { + 'user-agent': 'PT/NO-OP', }, - }; - - // Act - await middleware(vi.fn())(args); - - // Assess - expect(args.request.headers['user-agent']).toEqual( - `foo PT/my-feature/${version} PTEnv/NA` - ); - }); - - it('replaces the no-op Powertools UA with the the feature-specific one', async () => { - // Prepare - const args = { - request: { - headers: { - 'user-agent': 'PT/NO-OP', - }, + expected: `PT/my-feature/${version} PTEnv/NA`, + }, + { + case: 'leaves a feature-specific UA intact', + headers: { + 'user-agent': 'PT/other-feature/1.0 PTEnv/NA', }, - }; - - // Act - await middleware(vi.fn())(args); - - // Assess - expect(args.request.headers['user-agent']).toEqual( - `PT/my-feature/${version} PTEnv/NA` - ); - }); - - it('does not add the Powertools feature-specific UA if it is already present', async () => { + expected: 'PT/other-feature/1.0 PTEnv/NA', + }, + ])('it $case', async ({ headers, expected }) => { // Prepare const args = { request: { - headers: { - 'user-agent': 'PT/other-feature/1.0 PTEnv/NA', - }, + headers, }, }; @@ -172,9 +138,7 @@ describe('Helpers: awsSdk', () => { await middleware(vi.fn())(args); // Assess - expect(args.request.headers['user-agent']).toEqual( - 'PT/other-feature/1.0 PTEnv/NA' - ); + expect(args.request.headers['user-agent']).toEqual(expected); }); });