ApplicationInsights-node.js/Library/Tracestate.ts

84 строки
2.6 KiB
TypeScript

/**
* Helper class to manage parsing and strict-validation of tracestate header. W3C tracestate spec
* is documented at https://www.w3.org/TR/trace-context/#header-value
* @class Tracestate
*/
class Tracestate {
public static strict = true;
public fieldmap: string[] = [];
// if true, performs strict tracestate header checking, else just passes it along
constructor(id?: string) {
if (!id) {
return;
}
this.fieldmap = this.parseHeader(id);
}
public toString(): string {
const fieldarr = this.fieldmap;
if (!fieldarr || fieldarr.length == 0) {
return null;
}
return fieldarr.join(", ");
}
private static validateKeyChars(key: string): boolean {
const keyParts = key.split("@");
if (keyParts.length == 2) {
// Parse for tenant@vendor format
const tenant = keyParts[0].trim();
const vendor = keyParts[1].trim();
const tenantValid = Boolean(tenant.match(/^[\ ]?[a-z0-9\*\-\_/]{1,241}$/));
const vendorValid = Boolean(vendor.match(/^[\ ]?[a-z0-9\*\-\_/]{1,14}$/));
return tenantValid && vendorValid;
} else if (keyParts.length == 1) {
// Parse for standard key format
return Boolean(key.match(/^[\ ]?[a-z0-9\*\-\_/]{1,256}$/));
}
return false;
}
private parseHeader(id: string): string[] {
const res: string[] = [];
const keydeduper: {[key: string]: boolean} = {};
const parts = id.split(",");
if (parts.length > 32) return null;
for (let rawPart of parts) {
const part = rawPart.trim(); // trim out whitespace
if (part.length === 0) {
continue; // Discard empty pairs, but keep the rest of this tracestate
}
const pair = part.split("=");
// pair should contain exactly one "="
if (pair.length !== 2) {
return null; // invalid pair: discard entire tracestate
}
// Validate length and charset of this key
if (!Tracestate.validateKeyChars(pair[0])) {
return null;
}
// Assert uniqueness of this key
if (keydeduper[pair[0]]) {
return null; // duplicate key: discard entire tracestate
} else {
keydeduper[pair[0]] = true
}
// All checks passed -- add this part
res.push(part);
}
return res;
}
}
export = Tracestate;