Skip to content

Commit 6436855

Browse files
committed
feat(util-user-agent-*): support non-AWS clients
1 parent 63f33d9 commit 6436855

File tree

8 files changed

+101
-54
lines changed

8 files changed

+101
-54
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface DefaultUserAgentOptions {
2+
serviceId?: string;
3+
clientVersion: string;
4+
}

packages/util-user-agent-browser/src/index.native.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ it("should response basic browser default user agent", async () => {
44
// RN doesn't have userAgent in window.navigator.
55
//@ts-ignore mock no userAgent exists.
66
jest.spyOn(window.navigator, "userAgent", "get").mockReturnValue(undefined);
7-
const userAgent = await defaultUserAgent("s3", "0.1.0")();
8-
expect(userAgent).toContainEqual(["aws-sdk-js", "0.1.0"]);
9-
expect(userAgent).toContainEqual(["api/s3", "0.1.0"]);
7+
const userAgent = await defaultUserAgent({ serviceId: "s3", clientVersion: "0.1.0" })();
108
expect(userAgent).toContainEqual(["os/other"]);
119
expect(userAgent).toContainEqual(["md/rn"]);
10+
expect(userAgent).toContainEqual(["lang/js"]);
1211
jest.clearAllMocks();
1312
});
Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
11
import { Provider, UserAgent } from "@aws-sdk/types";
22

3+
import { DefaultUserAgentOptions } from "./configurations";
4+
35
/**
46
* Default provider to the user agent in ReactNative. It's a best effort to infer
57
* the device information. It uses bowser library to detect the browser and virsion
68
*/
7-
export const defaultUserAgent = (packageName: string, packageVersion: string): Provider<UserAgent> => {
9+
export const defaultUserAgent = ({
10+
serviceId,
11+
clientVersion,
12+
}: DefaultUserAgentOptions): Provider<UserAgent> => async () => {
813
// TODO: remove this post GA and version changed to 3.x.x
9-
const version = packageVersion.replace(/^1\./, "3.");
10-
return async () => [
11-
// sdk-metadata
12-
["aws-sdk-js", version],
13-
// api-metadata
14-
// TODO: use api name instead of package name
15-
[`api/${packageName}`, version],
14+
clientVersion = clientVersion.replace(/^1\./, "3.");
15+
const sections: UserAgent = [
1616
// os-metadata
1717
["os/other"],
1818
// language-metadata
1919
// ECMAScript edition doesn't matter in JS.
2020
["lang/js"],
2121
["md/rn"],
2222
];
23+
24+
if (serviceId) {
25+
// api-metadata
26+
// service Id may not appear in non-AWS clients
27+
sections.push([`api/${serviceId}`, clientVersion]);
28+
}
29+
30+
return sections;
2331
};
Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
import { defaultUserAgent } from ".";
22

3-
it("should response basic browser default user agent", async () => {
4-
const ua =
5-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36";
3+
const ua =
4+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36";
5+
6+
it("should populate metrics", async () => {
67
jest.spyOn(window.navigator, "userAgent", "get").mockReturnValue(ua);
7-
const userAgent = await defaultUserAgent("s3", "0.1.0")();
8+
const userAgent = await defaultUserAgent({ serviceId: "s3", clientVersion: "0.1.0" })();
89
expect(userAgent).toContainEqual(["aws-sdk-js", "0.1.0"]);
910
expect(userAgent).toContainEqual(["api/s3", "0.1.0"]);
1011
expect(userAgent).toContainEqual(["os/macOS", "10.15.7"]);
1112
expect(userAgent).toContainEqual(["md/browser", "Chrome_86.0.4240.111"]);
13+
expect(userAgent).toContainEqual(["lang/js"]);
14+
jest.clearAllMocks();
15+
});
16+
17+
it("should populate metrics when service id not available", async () => {
18+
jest.spyOn(window.navigator, "userAgent", "get").mockReturnValue(ua);
19+
const userAgent = await defaultUserAgent({ serviceId: undefined, clientVersion: "0.1.0" })();
20+
expect(userAgent).not.toContainEqual(["api/s3", "0.1.0"]);
1221
jest.clearAllMocks();
1322
});
Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
import { Provider, UserAgent } from "@aws-sdk/types";
22
import { parse } from "bowser";
33

4+
import { DefaultUserAgentOptions } from "./configurations";
5+
46
/**
57
* Default provider to the user agent in browsers. It's a best effort to infer
68
* the device information. It uses bowser library to detect the browser and virsion
79
*/
8-
export const defaultUserAgent = (packageName: string, packageVersion: string): Provider<UserAgent> => {
10+
export const defaultUserAgent = ({
11+
serviceId,
12+
clientVersion,
13+
}: DefaultUserAgentOptions): Provider<UserAgent> => async () => {
914
// TODO: remove this post GA and version changed to 3.x.x
10-
const version = packageVersion.replace(/^1\./, "3.");
15+
clientVersion = clientVersion.replace(/^1\./, "3.");
1116
const parsedUA = window?.navigator?.userAgent ? parse(window.navigator.userAgent) : undefined;
12-
return async () => [
17+
const sections: UserAgent = [
1318
// sdk-metadata
14-
["aws-sdk-js", version],
15-
// api-metadata
16-
// TODO: use api name instead of package name
17-
[`api/${packageName}`, version],
19+
["aws-sdk-js", clientVersion],
1820
// os-metadata
1921
[`os/${parsedUA?.os?.name || "other"}`, parsedUA?.os?.version],
2022
// language-metadata
@@ -23,4 +25,12 @@ export const defaultUserAgent = (packageName: string, packageVersion: string): P
2325
// browser vendor and version.
2426
["md/browser", `${parsedUA?.browser?.name ?? "unknown"}_${parsedUA?.browser?.version ?? "unknown"}`],
2527
];
28+
29+
if (serviceId) {
30+
// api-metadata
31+
// service Id may not appear in non-AWS clients
32+
sections.push([`api/${serviceId}`, clientVersion]);
33+
}
34+
35+
return sections;
2636
};

packages/util-user-agent-node/src/index.spec.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,30 @@ describe("defaultUserAgent", () => {
2828
});
2929

3030
it("should response basic node default user agent", async () => {
31-
const userAgent = await defaultUserAgent("s3", "0.1.0")();
31+
const userAgent = await defaultUserAgent({ serviceId: "s3", clientVersion: "0.1.0" })();
3232
expect(userAgent).toContainEqual(["aws-sdk-js", "0.1.0"]);
3333
expect(userAgent).toContainEqual(["api/s3", "0.1.0"]);
3434
expect(userAgent).toContainEqual(["os/darwin", "19.6.0"]);
35-
expect(userAgent).toContainEqual(["lang/nodejs", "14.13.1"]);
35+
expect(userAgent).toContainEqual(["lang/js"]);
36+
});
37+
38+
it("should skip api version if service id is not supplied", async () => {
39+
const userAgent = await defaultUserAgent({ serviceId: undefined, clientVersion: "0.1.0" })();
40+
expect(userAgent).not.toContainEqual(["api/s3", "0.1.0"]);
3641
});
3742

3843
it("should add AWS_EXECUTION_ENV", async () => {
3944
//@ts-ignore mock environmental variables
4045
mockEnv.AWS_EXECUTION_ENV = "lambda";
41-
const userAgent = await defaultUserAgent("s3", "0.1.0")();
46+
const userAgent = await defaultUserAgent({ serviceId: "s3", clientVersion: "0.1.0" })();
4247
expect(userAgent).toContainEqual(["exec-env/lambda"]);
4348
});
4449

4550
it("should load app id if available", async () => {
4651
mockAppIdLoader.mockClear();
4752
const appId = "appId12345";
4853
mockAppIdLoader.mockResolvedValue(appId);
49-
const userAgent = await defaultUserAgent("s3", "0.1.0")();
54+
const userAgent = await defaultUserAgent({ serviceId: "s3", clientVersion: "0.1.0" })();
5055
expect(userAgent).toContainEqual([`app/${appId}`]);
5156
});
5257
});

packages/util-user-agent-node/src/index.ts

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,50 @@ import { env, versions } from "process";
66
export const UA_APP_ID_ENV_NAME = "AWS_SDK_UA_APP_ID";
77
export const UA_APP_ID_INI_NAME = "sdk-ua-app-id";
88

9-
export const defaultUserAgent = (packageName: string, packageVersion: string): Provider<UserAgent> => {
9+
interface DefaultUserAgentOptions {
10+
serviceId?: string;
11+
clientVersion: string;
12+
}
13+
14+
/**
15+
* Collect metrics from runtime to put into user agent.
16+
*/
17+
export const defaultUserAgent = ({
18+
serviceId,
19+
clientVersion,
20+
}: DefaultUserAgentOptions): Provider<UserAgent> => async () => {
1021
// TODO: remove this post GA and version changed to 3.x.x
11-
const version = packageVersion.replace(/^1\./, "3.");
22+
clientVersion = clientVersion.replace(/^1\./, "3.");
1223
const sections: UserAgent = [
1324
// sdk-metadata
14-
["aws-sdk-js", version],
15-
// api-metadata
16-
// TODO: use api name instead of package name
17-
[`api/${packageName}`, version],
25+
["aws-sdk-js", clientVersion],
1826
// os-metadata
1927
[`os/${platform()}`, release()],
2028
// language-metadata
2129
// ECMAScript edition doesn't matter in JS, so no version needed.
2230
["lang/js"],
2331
["md/nodejs", `${versions.node}`],
2432
];
33+
34+
if (serviceId) {
35+
// api-metadata
36+
// service Id may not appear in non-AWS clients
37+
sections.push([`api/${serviceId}`, clientVersion]);
38+
}
39+
2540
if (env.AWS_EXECUTION_ENV) {
2641
// env-metadata
2742
sections.push([`exec-env/${env.AWS_EXECUTION_ENV}`]);
2843
}
29-
return async () => {
30-
const appId = await loadConfig<string | undefined>({
31-
environmentVariableSelector: (env) => env[UA_APP_ID_ENV_NAME],
32-
configFileSelector: (profile) => profile[UA_APP_ID_INI_NAME],
33-
default: undefined,
34-
})();
35-
if (appId) {
36-
sections.push([`app/${appId}`]);
37-
}
38-
return sections;
39-
};
44+
45+
const appId = await loadConfig<string | undefined>({
46+
environmentVariableSelector: (env) => env[UA_APP_ID_ENV_NAME],
47+
configFileSelector: (profile) => profile[UA_APP_ID_INI_NAME],
48+
default: undefined,
49+
})();
50+
if (appId) {
51+
sections.push([`app/${appId}`]);
52+
}
53+
54+
return sections;
4055
};

yarn.lock

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,19 @@
4545
dependencies:
4646
tslib "^1.11.1"
4747

48-
"@aws-sdk/types@^1.0.0-rc.1":
49-
version "1.0.0-rc.10"
50-
resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-1.0.0-rc.10.tgz#729127fbfac5da1a3368ffe6ec2e90acc9ad69c3"
51-
integrity sha512-9gwhYnkTNuYZ+etCtM4T8gjpZ0SWSXbzQxY34UjSS+dt3C/UnbX0J22tMahp/9Z1yCa9pihtXrkD+nO2xn7nVQ==
52-
53-
"@aws-sdk/util-locate-window@^1.0.0-rc.1":
48+
"@aws-sdk/[email protected]":
5449
version "1.0.0-rc.8"
55-
resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-1.0.0-rc.8.tgz#d28175aeb9c8ad3940242e615b1503632d3be33d"
56-
integrity sha512-TvqeA4fgmZ0A0x3K+qVj/OSWEFHGZjzpVuyXlm1EYOf7NQ9VWRlokEn1MYKuL+t7al9ZeQyi16D8Dn7DW1eidw==
50+
resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-1.0.0-rc.8.tgz#be7959dd564d27e94ca7e7008eb184679f2b2e20"
51+
integrity sha512-sRfbQpG8os3Kkecr/2q79UpekWyXhL7Kod04UnjIsAFJkQL1xHkyw7tSdW+7eiXoMCfRDa8VbE05tZK2YD9YuA==
5752
dependencies:
53+
"@aws-sdk/property-provider" "1.0.0-rc.8"
54+
"@aws-sdk/shared-ini-file-loader" "1.0.0-rc.8"
5855
tslib "^1.8.0"
5956

60-
"@aws-sdk/util-utf8-browser@^1.0.0-rc.1":
57+
"@aws-sdk/shared-ini-file-loader@1.0.0-rc.8":
6158
version "1.0.0-rc.8"
62-
resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-1.0.0-rc.8.tgz#bf1f1cfed8c024f43a7c43b643fdf2b4523b5973"
63-
integrity sha512-clncPMJ23rxCIkZ9LoUC8SowwZGxWyN2TwRb0XvW/Cv9EavkRgRCOrCpneGyC326lqtMKx36onnpaSRHxErUYw==
59+
resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-1.0.0-rc.8.tgz#36785c595480ad228da8ce81602c31fc909ca29c"
60+
integrity sha512-5MmUwfFncn5fPMBD9K24ioLD/S1C4Jz8eEv8tcluEXo8Tb5JDKyY0sJGJjfaTBpWpjZ3rhNDBWM3sWYtMlWPqA==
6461
dependencies:
6562
tslib "^1.8.0"
6663

0 commit comments

Comments
 (0)