Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions sdk/core/core-rest-pipeline/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

### Bugs Fixed

- Fix invalid format of "User-Agent" header value [Issue #36383](https://github.com/Azure/azure-sdk-for-js/issues/36383)

### Other Changes

## 1.22.1 (2025-09-11)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,28 +70,26 @@ function getBrandVersionString(brands: BrowserBrand[]): BrowserBrand | undefined
*/
export async function setPlatformSpecificData(map: Map<string, string>): Promise<void> {
const localNavigator = globalThis.navigator as NavigatorEx;
let osPlatform = "unknown";
let osInfo = "unknown";
if (localNavigator?.userAgentData) {
const entropyValues = await localNavigator.userAgentData.getHighEntropyValues([
"architecture",
"platformVersion",
]);
osPlatform = `${entropyValues.architecture}-${entropyValues.platform}-${entropyValues.platformVersion}`;
osInfo = `${entropyValues.platform} ${entropyValues.platformVersion}; ${entropyValues.architecture}`;

// Get the brand and version
const brand = getBrandVersionString(localNavigator.userAgentData.brands);
if (brand) {
map.set(brand.brand, brand.version);
map.set(brand.brand, `${brand.version} (${osInfo})`);
}
} else if (localNavigator?.platform) {
osPlatform = localNavigator.platform;
osInfo = localNavigator.platform;
const brand = getBrowserInfo(localNavigator.userAgent);
if (brand) {
map.set(brand.brand, brand.version);
map.set(brand.brand, `${brand.version} (${osInfo})`);
}
} else if (typeof globalThis.EdgeRuntime === "string") {
map.set("EdgeRuntime", globalThis.EdgeRuntime);
map.set("EdgeRuntime", `${globalThis.EdgeRuntime} (${osInfo})`);
}

map.set("OS", osPlatform);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export function getHeaderName(): string {
export async function setPlatformSpecificData(map: Map<string, string>): Promise<void> {
if (Platform.constants?.reactNativeVersion) {
const { major, minor, patch } = Platform.constants.reactNativeVersion;
map.set("react-native", `${major}.${minor}.${patch}`);
map.set("react-native", `${major}.${minor}.${patch} (${Platform.OS} ${Platform.Version})`);
}
map.set("OS", `${Platform.OS}-${Platform.Version}`);
}
9 changes: 4 additions & 5 deletions sdk/core/core-rest-pipeline/src/util/userAgentPlatform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,14 @@ export function getHeaderName(): string {
*/
export async function setPlatformSpecificData(map: Map<string, string>): Promise<void> {
if (process && process.versions) {
const osInfo = `${os.type()} ${os.release()}; ${os.arch()}`;
const versions = process.versions as ExtendedPlatformVersions;
if (versions.bun) {
map.set("Bun", versions.bun);
map.set("Bun", `${versions.bun} (${osInfo})`);
} else if (versions.deno) {
map.set("Deno", versions.deno);
map.set("Deno", `${versions.deno} (${osInfo})`);
} else if (versions.node) {
map.set("Node", versions.node);
map.set("Node", `${versions.node} (${osInfo})`);
}
}

map.set("OS", `(${os.arch()}-${os.type()}-${os.release()})`);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@ import { describe, it, assert } from "vitest";
import { setPlatformSpecificData } from "../../src/util/userAgentPlatform.js";

describe("userAgentPlatform", () => {
it("should set OS", async () => {
const map = new Map<string, string>();

await setPlatformSpecificData(map);

assert.ok(map.has("OS"));
});

it("should set the Browser Type", async () => {
const map = new Map<string, string>();

Expand Down
53 changes: 33 additions & 20 deletions sdk/core/core-rest-pipeline/test/node/userAgentPlatform.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { describe, it, assert, vi, afterEach } from "vitest";
import { describe, it, assert, vi, afterEach, beforeEach } from "vitest";
import { setPlatformSpecificData } from "../../src/util/userAgentPlatform.js";
import process from "process";
import os from "node:os";

describe("userAgentPlatform", () => {
vi.mock("node:process", async () => {
Expand All @@ -16,6 +17,22 @@ describe("userAgentPlatform", () => {
};
});

vi.mock("node:os", async () => {
const actual = await vi.importActual("node:os");
return {
default: {
...(actual as any).default,
versions: {},
},
};
});

beforeEach(() => {
(vi.mocked(os) as any).type = () => "Linux";
(vi.mocked(os) as any).release = () => "6.13.8";
(vi.mocked(os) as any).arch = () => "x64";
});

afterEach(() => {
vi.clearAllMocks();
});
Expand All @@ -26,10 +43,9 @@ describe("userAgentPlatform", () => {

await setPlatformSpecificData(map);

assert.ok(map.has("OS"));
assert.notOk(map.has("Node"));
assert.notOk(map.has("Deno"));
assert.notOk(map.has("Bun"));
assert.isNotTrue(map.has("Node"));
assert.isNotTrue(map.has("Deno"));
assert.isNotTrue(map.has("Bun"));
});

it("should handle a Node.js process.versions with Bun", async () => {
Expand All @@ -38,11 +54,10 @@ describe("userAgentPlatform", () => {

await setPlatformSpecificData(map);

assert.ok(map.has("OS"));
assert.ok(map.has("Bun"));
assert.equal(map.get("Bun"), "1.0.0");
assert.notOk(map.has("Node"));
assert.notOk(map.has("Deno"));
assert.isTrue(map.has("Bun"));
assert.equal(map.get("Bun"), ("1.0.0 (Linux 6.13.8; x64)"));
assert.isNotTrue(map.has("Node"));
assert.isNotTrue(map.has("Deno"));
});

it("should handle a Node.js process.versions with Deno", async () => {
Expand All @@ -51,11 +66,10 @@ describe("userAgentPlatform", () => {

await setPlatformSpecificData(map);

assert.ok(map.has("OS"));
assert.ok(map.has("Deno"));
assert.equal(map.get("Deno"), "2.0.0");
assert.notOk(map.has("Node"));
assert.notOk(map.has("Bun"));
assert.isTrue(map.has("Deno"));
assert.equal(map.get("Deno"), ("2.0.0 (Linux 6.13.8; x64)"));
assert.isNotTrue(map.has("Node"));
assert.isNotTrue(map.has("Bun"));
});

it("should handle a Node.js process.versions", async () => {
Expand All @@ -64,10 +78,9 @@ describe("userAgentPlatform", () => {

await setPlatformSpecificData(map);

assert.ok(map.has("OS"));
assert.ok(map.has("Node"));
assert.equal(map.get("Node"), "20.0.0");
assert.notOk(map.has("Deno"));
assert.notOk(map.has("Bun"));
assert.isTrue(map.has("Node"));
assert.equal(map.get("Node"), ("20.0.0 (Linux 6.13.8; x64)"));
assert.isNotTrue(map.has("Deno"));
assert.isNotTrue(map.has("Bun"));
});
});
2 changes: 2 additions & 0 deletions sdk/core/ts-http-runtime/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

### Bugs Fixed

- Fix invalid format of "User-Agent" header value [Issue #36383](https://github.com/Azure/azure-sdk-for-js/issues/36383)

### Other Changes

## 0.3.1 (2025-09-11)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,28 +70,26 @@ function getBrandVersionString(brands: BrowserBrand[]): BrowserBrand | undefined
*/
export async function setPlatformSpecificData(map: Map<string, string>): Promise<void> {
const localNavigator = globalThis.navigator as NavigatorEx;
let osPlatform = "unknown";
let osInfo = "unknown";
if (localNavigator?.userAgentData) {
const entropyValues = await localNavigator.userAgentData.getHighEntropyValues([
"architecture",
"platformVersion",
]);
osPlatform = `${entropyValues.architecture}-${entropyValues.platform}-${entropyValues.platformVersion}`;
osInfo = `${entropyValues.platform} ${entropyValues.platformVersion}; ${entropyValues.architecture}`;

// Get the brand and version
const brand = getBrandVersionString(localNavigator.userAgentData.brands);
if (brand) {
map.set(brand.brand, brand.version);
map.set(brand.brand, `${brand.version} (${osInfo})`);
}
} else if (localNavigator?.platform) {
osPlatform = localNavigator.platform;
osInfo = localNavigator.platform;
const brand = getBrowserInfo(localNavigator.userAgent);
if (brand) {
map.set(brand.brand, brand.version);
map.set(brand.brand, `${brand.version} (${osInfo})`);
}
} else if (typeof globalThis.EdgeRuntime === "string") {
map.set("EdgeRuntime", globalThis.EdgeRuntime);
map.set("EdgeRuntime", `${globalThis.EdgeRuntime} (${osInfo})`);
}

map.set("OS", osPlatform);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export function getHeaderName(): string {
export async function setPlatformSpecificData(map: Map<string, string>): Promise<void> {
if (Platform.constants?.reactNativeVersion) {
const { major, minor, patch } = Platform.constants.reactNativeVersion;
map.set("react-native", `${major}.${minor}.${patch}`);
map.set("react-native", `${major}.${minor}.${patch} (${Platform.OS} ${Platform.Version})`);
}
map.set("OS", `${Platform.OS}-${Platform.Version}`);
}
9 changes: 4 additions & 5 deletions sdk/core/ts-http-runtime/src/util/userAgentPlatform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,14 @@ export function getHeaderName(): string {
*/
export async function setPlatformSpecificData(map: Map<string, string>): Promise<void> {
if (process && process.versions) {
const osInfo = `${os.type()} ${os.release()}; ${os.arch()}`;
const versions = process.versions as ExtendedPlatformVersions;
if (versions.bun) {
map.set("Bun", versions.bun);
map.set("Bun", `${versions.bun} (${osInfo})`);
} else if (versions.deno) {
map.set("Deno", versions.deno);
map.set("Deno", `${versions.deno} (${osInfo})`);
} else if (versions.node) {
map.set("Node", versions.node);
map.set("Node", `${versions.node} (${osInfo})`);
}
}

map.set("OS", `(${os.arch()}-${os.type()}-${os.release()})`);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@ import { describe, it, assert } from "vitest";
import { setPlatformSpecificData } from "../../src/util/userAgentPlatform.js";

describe("userAgentPlatform", () => {
it("should set OS", async () => {
const map = new Map<string, string>();

await setPlatformSpecificData(map);

assert.ok(map.has("OS"));
});

it("should set the Browser Type", async () => {
const map = new Map<string, string>();

Expand Down
53 changes: 33 additions & 20 deletions sdk/core/ts-http-runtime/test/node/userAgentPlatform.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { describe, it, assert, vi, afterEach } from "vitest";
import { describe, it, assert, vi, afterEach, beforeEach } from "vitest";
import { setPlatformSpecificData } from "../../src/util/userAgentPlatform.js";
import process from "node:process";
import os from "node:os";

describe("userAgentPlatform", () => {
vi.mock("node:process", async () => {
Expand All @@ -16,6 +17,22 @@ describe("userAgentPlatform", () => {
};
});

vi.mock("node:os", async () => {
const actual = await vi.importActual("node:os");
return {
default: {
...(actual as any).default,
versions: {},
},
};
});

beforeEach(() => {
(vi.mocked(os) as any).type = () => "Linux";
(vi.mocked(os) as any).release = () => "6.13.8";
(vi.mocked(os) as any).arch = () => "x64";
});

afterEach(() => {
vi.clearAllMocks();
});
Expand All @@ -26,10 +43,9 @@ describe("userAgentPlatform", () => {

await setPlatformSpecificData(map);

assert.ok(map.has("OS"));
assert.notOk(map.has("Node"));
assert.notOk(map.has("Deno"));
assert.notOk(map.has("Bun"));
assert.isNotTrue(map.has("Node"));
assert.isNotTrue(map.has("Deno"));
assert.isNotTrue(map.has("Bun"));
});

it("should handle a Node.js process.versions with Bun", async () => {
Expand All @@ -38,11 +54,10 @@ describe("userAgentPlatform", () => {

await setPlatformSpecificData(map);

assert.ok(map.has("OS"));
assert.ok(map.has("Bun"));
assert.equal(map.get("Bun"), "1.0.0");
assert.notOk(map.has("Node"));
assert.notOk(map.has("Deno"));
assert.isTrue(map.has("Bun"));
assert.equal(map.get("Bun"), ("1.0.0 (Linux 6.13.8; x64)"));
assert.isNotTrue(map.has("Node"));
assert.isNotTrue(map.has("Deno"));
});

it("should handle a Node.js process.versions with Deno", async () => {
Expand All @@ -51,11 +66,10 @@ describe("userAgentPlatform", () => {

await setPlatformSpecificData(map);

assert.ok(map.has("OS"));
assert.ok(map.has("Deno"));
assert.equal(map.get("Deno"), "2.0.0");
assert.notOk(map.has("Node"));
assert.notOk(map.has("Bun"));
assert.isTrue(map.has("Deno"));
assert.equal(map.get("Deno"), ("2.0.0 (Linux 6.13.8; x64)"));
assert.isNotTrue(map.has("Node"));
assert.isNotTrue(map.has("Bun"));
});

it("should handle a Node.js process.versions", async () => {
Expand All @@ -64,10 +78,9 @@ describe("userAgentPlatform", () => {

await setPlatformSpecificData(map);

assert.ok(map.has("OS"));
assert.ok(map.has("Node"));
assert.equal(map.get("Node"), "20.0.0");
assert.notOk(map.has("Deno"));
assert.notOk(map.has("Bun"));
assert.isTrue(map.has("Node"));
assert.equal(map.get("Node"), ("20.0.0 (Linux 6.13.8; x64)"));
assert.isNotTrue(map.has("Deno"));
assert.isNotTrue(map.has("Bun"));
});
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

/*
* NOTE: When moving this file, please update "react-native" section in package.json.
*/
const { Platform } = require("react-native"); // eslint-disable-line @typescript-eslint/no-require-imports

/**
Expand All @@ -13,15 +10,5 @@ const { Platform } = require("react-native"); // eslint-disable-line @typescript
*/
export function getRuntimeInfo(): string {
const { major, minor, patch } = Platform.constants.reactNativeVersion;
const runtimeInfo = {
key: "react-native",
value: `${major}.${minor}.${patch}`,
};

const osInfo = {
key: "OS",
value: `${Platform.OS}-${Platform.Version}`,
};

return `${runtimeInfo.key}/${runtimeInfo.value} ${osInfo.key}/${osInfo.value}`;
return `react-native/${major}.${minor}.${patch} (${Platform.OS} ${Platform.Version})`;
}
Loading
Loading