Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
7146c33
udpate metrics for mqtt3
xiazhvera Jan 6, 2026
60ae90e
update aws-c-mqtt
xiazhvera Jan 6, 2026
9ca5d2d
set metrics for mqtt5 client
xiazhvera Jan 7, 2026
daeaf35
fix libray import
xiazhvera Jan 7, 2026
c5dcafb
update test as we are removing metrics from username
xiazhvera Jan 7, 2026
2ecc0b4
fix metrics implementation
xiazhvera Jan 7, 2026
ff625a4
fix dependency path
xiazhvera Jan 7, 2026
34f5f77
fix mqtt5 metrics. The mqtt5 custom auth should fail with this commit
xiazhvera Jan 7, 2026
6bf3e55
update custom auth test
xiazhvera Jan 7, 2026
33676ad
update browser metrics
xiazhvera Jan 7, 2026
c48c9cb
clean up
xiazhvera Jan 7, 2026
c839553
add enable_metrics option for mqtt3 browser
xiazhvera Jan 8, 2026
9f4d041
revert mqtt3 metrics changes
xiazhvera Jan 8, 2026
e7eee32
remove enable metrics from browser
xiazhvera Jan 8, 2026
d2d68b0
remove enablemetrics from browser
xiazhvera Jan 8, 2026
402af38
clean up
xiazhvera Jan 8, 2026
5744019
fix basic auth test
xiazhvera Jan 8, 2026
503b0be
Merge branch 'main' into iot_metrics
xiazhvera Jan 14, 2026
ddde402
update to append metrics
xiazhvera Jan 15, 2026
34952e5
fix test SDK naming
xiazhvera Jan 15, 2026
c9cc6b9
Merge branch 'main' into iot_metrics
xiazhvera Jan 15, 2026
0a38686
kick ci
xiazhvera Jan 15, 2026
969d97e
Merge branch 'iot_metrics' of https://github.com/awslabs/aws-crt-node…
xiazhvera Jan 15, 2026
956dbbe
kick ci
xiazhvera Jan 15, 2026
6727fd3
and retry
xiazhvera Jan 16, 2026
93fcba5
Merge branch 'main' into iot_metrics
xiazhvera Jan 30, 2026
892c18f
set metrics should not fail on client
xiazhvera Feb 12, 2026
ec06c63
do not fail mqtt5 client with invalid metrics
xiazhvera Feb 12, 2026
1823b66
update metrics structure
xiazhvera Feb 13, 2026
16fd073
update aws-c-mqtt
xiazhvera Feb 17, 2026
970dfd1
wip mqtt3 basic auth failure
xiazhvera Mar 2, 2026
f06e2b9
add mqtt5 custom auth with metrics
xiazhvera Mar 2, 2026
efadb0c
fix custom auth username/pw
xiazhvera Mar 2, 2026
196522d
clean up mqtt3 metrics enabled test
xiazhvera Mar 2, 2026
21c9c5d
Merge branch 'main' into iot_metrics
xiazhvera Mar 9, 2026
6c8b2dc
update comments for enable metrics
xiazhvera Mar 18, 2026
7693055
update cr comments
xiazhvera Mar 27, 2026
c831255
Merge branch 'main' into iot_metrics
xiazhvera Apr 3, 2026
d20b464
create MqttConnectionConfigBase to share
xiazhvera Apr 20, 2026
7a8dc39
export MqttConnectionConfigBase
xiazhvera Apr 20, 2026
31c2f13
Merge branch 'main' of https://github.com/awslabs/aws-crt-nodejs into…
xiazhvera Apr 20, 2026
b1cb699
update mqtt5 client options
xiazhvera Apr 20, 2026
51fa175
clean up
xiazhvera Apr 20, 2026
49e421a
lint
xiazhvera Apr 20, 2026
22c7c27
fix test
xiazhvera Apr 20, 2026
0486d91
fix test
xiazhvera Apr 20, 2026
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
7 changes: 4 additions & 3 deletions lib/browser/aws_iot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { SocketOptions } from "./io";
import { MqttClientConnection, MqttConnectionConfig, MqttWill } from "./mqtt";
import * as platform from "../common/platform";
import * as iot_shared from "../common/aws_iot_shared"
import { SDK_NAME } from "../common/mqtt_shared";

/**
* Builder functions to create a {@link MqttConnectionConfig} which can then be used to create
Expand Down Expand Up @@ -328,12 +329,12 @@ export class AwsIotMqttConnectionConfigBuilder {

// Add the metrics string
if (this.params.username == undefined || this.params.username == null || this.params.username == "") {
this.params.username = "?SDK=NodeJSv2&Version="
this.params.username = `?SDK=${SDK_NAME}&Version=`
} else {
if (this.params.username.indexOf("?") != -1) {
this.params.username += "&SDK=NodeJSv2&Version="
this.params.username += `&SDK=${SDK_NAME}&Version=`
} else {
this.params.username += "?SDK=NodeJSv2&Version="
this.params.username += `?SDK=${SDK_NAME}&Version=`
}
}
this.params.username += platform.crt_version()
Expand Down
84 changes: 5 additions & 79 deletions lib/browser/mqtt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
Payload,
MqttRequest,
MqttSubscribeRequest,
MqttWill,
OnMessageCallback,
MqttConnectionConnected,
MqttConnectionDisconnected,
Expand All @@ -36,12 +35,13 @@ import {
OnConnectionFailedResult,
OnConnectionClosedResult
} from "../common/mqtt";
import {normalize_payload, normalize_payload_to_buffer} from "../common/mqtt_shared";
import {normalize_payload, normalize_payload_to_buffer, MqttConnectionConfigBase} from "../common/mqtt_shared";

export {
QoS, Payload, MqttRequest, MqttSubscribeRequest, MqttWill, OnMessageCallback, MqttConnectionConnected, MqttConnectionDisconnected,
MqttConnectionResumed, OnConnectionSuccessResult, OnConnectionFailedResult, OnConnectionClosedResult
} from "../common/mqtt";
export { MqttConnectionConfigBase } from "../common/mqtt_shared";

/**
* Listener signature for event emitted from an {@link MqttClientConnection} when an error occurs
Expand Down Expand Up @@ -110,88 +110,14 @@ export type AWSCredentials = auth.AWSCredentials;
/**
* Configuration options for an MQTT connection
*
* Extends {@link MqttConnectionConfigBase} with browser-specific options.
*
* @category MQTT
*/
export interface MqttConnectionConfig {
/**
* ID to place in CONNECT packet. Must be unique across all devices/clients.
* If an ID is already in use, the other client will be disconnected.
*/
client_id: string;

/** Server name to connect to */
host_name: string;

/** Server port to connect to */
port: number;

export interface MqttConnectionConfig extends MqttConnectionConfigBase {
/** Socket options, ignored in browser */
socket_options: SocketOptions;

/**
* Whether or not to start a clean session with each reconnect.
* If True, the server will forget all subscriptions with each reconnect.
* Set False to request that the server resume an existing session
* or start a new session that may be resumed after a connection loss.
* The `session_present` bool in the connection callback informs
* whether an existing session was successfully resumed.
* If an existing session is resumed, the server remembers previous subscriptions
* and sends messages (with QoS1 or higher) that were published while the client was offline.
*/
clean_session?: boolean;

/**
* The keep alive value, in seconds, to send in CONNECT packet.
* A PING will automatically be sent at this interval.
* The server will assume the connection is lost if no PING is received after 1.5X this value.
* This duration must be longer than {@link ping_timeout}.
*/
keep_alive?: number;

/**
* Milliseconds to wait for ping response before client assumes
* the connection is invalid and attempts to reconnect.
* This duration must be shorter than keep_alive_secs.
* Alternatively, TCP keep-alive via :attr:`SocketOptions.keep_alive`
* may accomplish this in a more efficient (low-power) scenario,
* but keep-alive options may not work the same way on every platform and OS version.
*/
ping_timeout?: number;

/**
* Milliseconds to wait for the response to the operation requires response by protocol.
* Set to zero to disable timeout. Otherwise, the operation will fail if no response is
* received within this amount of time after the packet is written to the socket.
* It applied to PUBLISH (QoS>0) and UNSUBSCRIBE now.
*/
protocol_operation_timeout?: number;

/**
* Minimum seconds to wait between reconnect attempts.
* Must be <= {@link reconnect_max_sec}.
* Wait starts at min and doubles with each attempt until max is reached.
*/
reconnect_min_sec?: number;

/**
* Maximum seconds to wait between reconnect attempts.
* Must be >= {@link reconnect_min_sec}.
* Wait starts at min and doubles with each attempt until max is reached.
*/
reconnect_max_sec?: number;

/**
* Will to send with CONNECT packet. The will is
* published by the server when its connection to the client is unexpectedly lost.
*/
will?: MqttWill;

/** Username to connect with */
username?: string;

/** Password to connect with */
password?: string;

/** Options for the underlying websocket connection */
websocket?: WebsocketOptions;

Expand Down
57 changes: 4 additions & 53 deletions lib/browser/mqtt5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import * as auth from "./auth";

export * from "../common/mqtt5";
export * from '../common/mqtt5_packet';
export { Mqtt5ClientConfigBase } from "../common/mqtt_shared";

/**
* Factory function that allows the user to completely control the url used to form the websocket handshake
Expand Down Expand Up @@ -124,66 +125,16 @@ export interface Mqtt5WebsocketConfig {
/**
* Configuration options for mqtt5 client creation.
*/
export interface Mqtt5ClientConfig {

/**
* Host name of the MQTT server to connect to.
*/
hostName: string;

/**
* Network port of the MQTT server to connect to.
*/
port: number;

/**
* Controls how the MQTT5 client should behave with respect to MQTT sessions.
*/
sessionBehavior? : mqtt5.ClientSessionBehavior;

/**
* Controls how the reconnect delay is modified in order to smooth out the distribution of reconnection attempt
* timepoints for a large set of reconnecting clients.
*/
retryJitterMode? : mqtt5.RetryJitterType;

/**
* Minimum amount of time to wait to reconnect after a disconnect. Exponential backoff is performed with jitter
* after each connection failure.
*/
minReconnectDelayMs? : number;

/**
* Maximum amount of time to wait to reconnect after a disconnect. Exponential backoff is performed with jitter
* after each connection failure.
*/
maxReconnectDelayMs? : number;

/**
* Amount of time that must elapse with an established connection before the reconnect delay is reset to the minimum.
* This helps alleviate bandwidth-waste in fast reconnect cycles due to permission failures on operations.
*/
minConnectedTimeToResetReconnectDelayMs? : number;

/**
* All configurable options with respect to the CONNECT packet sent by the client, including the will. These
* connect properties will be used for every connection attempt made by the client.
*/
connectProperties?: mqtt5_packet.ConnectPacket;
export interface Mqtt5ClientConfig extends mqtt_shared.Mqtt5ClientConfigBase {

/**
* Overall time interval to wait to establish an MQTT connection. If a complete MQTT connection (from socket
* establishment all the way up to CONNACK receipt) has not been established before this timeout expires,
* the connection attempt will be considered a failure.
*/
connectTimeoutMs? : number;

/**
* Additional controls for client behavior with respect to topic alias usage.
*
* If this setting is left undefined, then topic aliasing behavior will be disabled.
* @group Browser-only
*/
topicAliasingOptions? : mqtt5.TopicAliasingOptions
connectTimeoutMs? : number;

/**
* Options for the underlying websocket connection
Expand Down
14 changes: 7 additions & 7 deletions lib/common/aws_iot_shared.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,36 @@
*/

import * as iot_shared from "./aws_iot_shared";
import { SDK_NAME } from "./mqtt_shared";

jest.setTimeout(10000);

test('Aws IoT Mqtt5 Username Construction - No Custom Auth', async () => {
let finalUsername : string = iot_shared.buildMqtt5FinalUsername(undefined);

expect(finalUsername).toEqual(expect.stringContaining("?SDK=NodeJSv2&Version="));
expect(finalUsername).toEqual(expect.stringContaining(`?SDK=${SDK_NAME}&Version=`));
});

test('Aws IoT Mqtt5 Username Construction - Empty custom auth', async () => {
let finalUsername : string = iot_shared.buildMqtt5FinalUsername({});

expect(finalUsername).toEqual(expect.stringContaining("?SDK=NodeJSv2&Version="));
expect(finalUsername).toEqual(expect.stringContaining(`?SDK=${SDK_NAME}&Version=`));
});


test('Aws IoT Mqtt5 Username Construction - Simple username', async () => {
let finalUsername : string = iot_shared.buildMqtt5FinalUsername({
username: "Derp"
});

expect(finalUsername).toEqual(expect.stringContaining("Derp?SDK=NodeJSv2&Version="));
expect(finalUsername).toEqual(expect.stringContaining(`Derp?SDK=${SDK_NAME}&Version=`));
});

test('Aws IoT Mqtt5 Username Construction - Query param username', async () => {
let finalUsername : string = iot_shared.buildMqtt5FinalUsername({
username: "Derp?Param1=Value1"
});

expect(finalUsername).toEqual(expect.stringContaining("Derp?Param1=Value1&SDK=NodeJSv2&Version="));
expect(finalUsername).toEqual(expect.stringContaining(`Derp?Param1=Value1&SDK=${SDK_NAME}&Version=`));
});

test('Aws IoT Mqtt5 Username Construction - Authorizer Name', async () => {
Expand All @@ -42,7 +42,7 @@ test('Aws IoT Mqtt5 Username Construction - Authorizer Name', async () => {
authorizerName: "MyAuthorizer"
});

expect(finalUsername).toEqual(expect.stringContaining("Hello?x-amz-customauthorizer-name=MyAuthorizer&SDK=NodeJSv2&Version="));
expect(finalUsername).toEqual(expect.stringContaining(`Hello?x-amz-customauthorizer-name=MyAuthorizer&SDK=${SDK_NAME}&Version=`));
});

test('Aws IoT Mqtt5 Username Construction - Token Signing', async () => {
Expand All @@ -54,7 +54,7 @@ test('Aws IoT Mqtt5 Username Construction - Token Signing', async () => {
tokenSignature: "SignedToken"
});

expect(finalUsername).toEqual(expect.stringContaining("Hello?x-amz-customauthorizer-name=MyAuthorizer&MyToken=TheToken&x-amz-customauthorizer-signature=SignedToken&SDK=NodeJSv2&Version="));
expect(finalUsername).toEqual(expect.stringContaining(`Hello?x-amz-customauthorizer-name=MyAuthorizer&MyToken=TheToken&x-amz-customauthorizer-signature=SignedToken&SDK=${SDK_NAME}&Version=`));
});

test('Aws IoT Mqtt5 Username Construction Failure - Missing token key name', async () => {
Expand Down
5 changes: 3 additions & 2 deletions lib/common/aws_iot_shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import * as platform from "./platform";
import * as mqtt5_packet from "./mqtt5_packet";
import * as utils from "./utils";
import { SDK_NAME } from "./mqtt_shared";

/**
* A helper function to add parameters to the username in with_custom_authorizer function
Expand Down Expand Up @@ -204,7 +205,7 @@ function addParam(paramName: string, paramValue: string | undefined, paramSet: [
*
* @internal
*/
export function buildMqtt5FinalUsername(customAuthConfig?: MqttConnectCustomAuthConfig) : string {
export function buildMqtt5FinalUsername(customAuthConfig?: MqttConnectCustomAuthConfig): string {

let path : string = "";
let paramList : [string, string][] = [];
Expand Down Expand Up @@ -241,7 +242,7 @@ export function buildMqtt5FinalUsername(customAuthConfig?: MqttConnectCustomAuth
}
}

paramList.push(["SDK", "NodeJSv2"]);
paramList.push(["SDK", SDK_NAME]);
paramList.push(["Version", platform.crt_version()]);

return (path ?? "") + "?" + paramList.map((value : [string, string]) => `${value[0]}=${value[1]}`).join("&");
Expand Down
2 changes: 1 addition & 1 deletion lib/common/mqtt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,4 @@ export const DEFAULT_RECONNECT_MAX_SEC = 128;
*
* @category MQTT
*/
export const DEFAULT_RECONNECT_MIN_SEC = 1;
export const DEFAULT_RECONNECT_MIN_SEC = 1;
Loading
Loading