@@ -172,85 +172,120 @@ export function calculateNextReconnectDelay(context: ReconnectDelayContext) : nu
172172 return delay ;
173173}
174174
175- interface QueryParsedUsername {
176- prefix ?: string ,
177- queryParams : [ string , string ] [ ]
175+ class ParsedUsername {
176+ prefix : string = "" ;
177+ queryParams : [ string , string ] [ ] = new Array < [ string , string ] > ;
178+ // metadata: [string, string][] = new Array<[string, string]>;
178179}
179180
180- function parseUsernameAsQueryString ( username ?: string ) : QueryParsedUsername {
181+ const METADATA_KEY : string = "Metadata" ;
182+ const SDK_KEY : string = "SDK" ;
183+ const PLATFORM_KEY : string = "Platform" ;
184+ const BROWSER_PLATFORM_VALUE : string = "Browser" ;
185+ const BROWSER_METADATA_KEY : string = "Browser" ;
186+
187+ function parseDelimitedKeyValueString ( input : string , pairDelimiter : string , kvDelimeter : string ) : Array < [ string , string ] > | null {
188+ let kvPairs = new Array < [ string , string ] > ;
189+
190+ let pairs = input . split ( pairDelimiter ) ;
191+ for ( let pair of pairs ) {
192+ let kvDelimeterIndex = pair . indexOf ( kvDelimeter ) ;
193+ if ( kvDelimeterIndex < 0 ) {
194+ kvPairs . push ( [ pair , "" ] ) ;
195+ }
196+
197+ let value = pair . substring ( kvDelimeterIndex + 1 ) ;
198+ kvPairs . push ( [ pair . substring ( 0 , kvDelimeterIndex ) , value ] ) ;
199+ }
200+
201+ if ( kvPairs . length > 0 ) {
202+ return kvPairs ;
203+ }
204+
205+ return null ;
206+ }
207+
208+ function parseUsername ( username ?: string ) : ParsedUsername {
209+ let parsed = new ParsedUsername ( ) ;
210+
181211 if ( ! username ) {
182- return {
183- queryParams : [ ]
184- } ;
212+ return parsed ;
185213 }
186214
187215 let queryIndex = username . lastIndexOf ( '?' ) ;
188216 if ( queryIndex < 0 ) {
189- return {
190- prefix : username ,
191- queryParams : [ ]
192- }
217+ parsed . prefix = username ;
218+ return parsed ;
193219 }
194220
195- let parsed : QueryParsedUsername = {
196- prefix : username . substring ( 0 , queryIndex ) ,
197- queryParams : [ ]
198- }
221+ parsed . prefix = username . substring ( 0 , queryIndex ) ;
199222
200223 let remaining = username . substring ( queryIndex + 1 ) ;
201- while ( remaining . length > 0 ) {
202- let ampersandIndex = remaining . indexOf ( '&' ) ;
203- let pair : string ;
204- if ( ampersandIndex < 0 ) {
205- pair = remaining ;
206- remaining = "" ;
207- } else {
208- pair = remaining . substring ( 0 , ampersandIndex ) ;
209- remaining = remaining . substring ( ampersandIndex + 1 ) ;
210- }
211-
212- let equalsIndex = pair . indexOf ( '=' ) ;
213- if ( equalsIndex < 0 ) {
214- // @ts -ignore
215- parsed . queryParams . push ( [
216- pair ,
217- ""
218- ] ) ;
219- } else {
220- // @ts -ignore
221- parsed . queryParams . push ( [
222- pair . substring ( 0 , equalsIndex ) ,
223- pair . substring ( equalsIndex + 1 )
224- ] ) ;
225- }
224+ let topLevelPairs = parseDelimitedKeyValueString ( remaining , "&" , "=" ) ;
225+ if ( topLevelPairs ) {
226+ parsed . queryParams = topLevelPairs ;
227+ /*
228+ let metadataValue = topLevelPairs.get(METADATA_KEY);
229+ if (metadataValue !== undefined && metadataValue.length >= 2 && metadataValue[0] == '(' && metadataValue[metadataValue.length - 1] == ')') {
230+ metadataValue = metadataValue.substring(1, metadataValue.length - 2);
231+ let metadataMap = parseDelimitedKeyValueString(metadataValue, ";", "=");
232+ if (metadataMap) {
233+ parsed.metadata = metadataMap;
234+ parsed.queryParams.delete(METADATA_KEY);
235+ }
236+ }*/
226237 }
227238
228239 return parsed ;
229240}
230241
231- function addTopLevelQueryParamIfNonexistent ( parsed : QueryParsedUsername , pair : [ string , string ] ) {
232- let key = pair [ 0 ] ;
242+ function addTopLevelPairIfNonexistent ( parsed : ParsedUsername , key : string , value : string ) {
243+ if ( parsed . queryParams . has ( key ) ) {
244+ return ;
245+ }
246+
247+ parsed . queryParams . set ( key , value ) ;
248+ }
249+
250+ function addMetadataPairIfNonExistent ( parsed : ParsedUsername , key : string , value : string ) {
251+ // can't add metadata pairs if there's an existing top-level metadata entry that is malformed
252+ if ( parsed . queryParams . has ( METADATA_KEY ) ) {
253+ return ;
254+ }
233255
234- let existingIndex = parsed . queryParams . findIndex ( ( element ) => element [ 0 ] === key ) ;
235- if ( existingIndex < 0 ) {
236- parsed . queryParams . push ( pair ) ;
256+ let metadataValue = parsed . metadata . get ( key ) ;
257+ if ( metadataValue !== undefined ) {
258+ return ;
237259 }
260+
261+ parsed . metadata . set ( key , value ) ;
238262}
239263
240- function buildUsernameFromQueryParse ( parsed : QueryParsedUsername ) : string {
241- let prefix = parsed . prefix ?? "" ;
242- return prefix + "?" + parsed . queryParams . map ( ( pair ) => pair . join ( "=" ) ) . join ( "&" ) ;
264+ function buildUsernameFromQueryParse ( parsed : ParsedUsername ) : string {
265+ let metadataValue = undefined ;
266+ if ( ! parsed . queryParams . get ( METADATA_KEY ) && parsed . metadata . size > 0 ) {
267+ let innerValue = Array . from ( parsed . metadata . entries ( ) ) . map ( ( pair ) => pair . join ( "=" ) ) . join ( ";" ) ;
268+ metadataValue = "(" + innerValue + ")" ;
269+ }
270+
271+ let topLevelParamArray = Array . from ( parsed . queryParams . entries ( ) ) ;
272+ if ( metadataValue !== undefined ) {
273+ topLevelParamArray . push ( [ METADATA_KEY , metadataValue ] ) ;
274+ }
275+
276+ let queryParamValue = topLevelParamArray . map ( ( pair ) => pair . join ( "=" ) ) . join ( ":" ) ;
277+
278+ return parsed . prefix + "?" + queryParamValue ;
243279}
244280
245281export function buildFinalUsernameFromMetrics ( metrics : mqtt_shared . AwsIoTDeviceSDKMetrics , username ?: string ) : string {
246- let parsedAsQuery = parseUsernameAsQueryString ( username ) ;
282+ let parsed = parseUsername ( username ) ;
247283
248- addTopLevelQueryParamIfNonexistent ( parsedAsQuery , [ "SDK" , metrics . libraryName ] ) ;
284+ addTopLevelPairIfNonexistent ( parsed , SDK_KEY , metrics . libraryName ) ;
285+ addTopLevelPairIfNonexistent ( parsed , PLATFORM_KEY , BROWSER_PLATFORM_VALUE ) ;
249286
250- //let browserInfo = window?.navigator?.userAgent ?? "unknown";
251- //addTopLevelQueryParamIfNonexistent(parsedAsQuery, ["Platform", `Browser(${browserInfo})`]);
252- // TODO: add browserInfo as a metadata field
253- addTopLevelQueryParamIfNonexistent ( parsedAsQuery , [ "Platform" , "Browser" ] ) ;
287+ let browserInfo = window ?. navigator ?. userAgent ?? "unknown" ;
288+ addMetadataPairIfNonExistent ( parsed , BROWSER_METADATA_KEY , browserInfo ) ;
254289
255- return buildUsernameFromQueryParse ( parsedAsQuery ) ;
290+ return buildUsernameFromQueryParse ( parsed ) ;
256291}
0 commit comments