diff --git a/SignalR.sln b/SignalR.sln
index 3a2b804d30..be48af096d 100644
--- a/SignalR.sln
+++ b/SignalR.sln
@@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{C4BC9889-B49F-41B6-806B-F84941B2549B}"
+ ProjectSection(SolutionItems) = preProject
+ EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SignalRSamples", "samples\SignalRSamples\SignalRSamples.csproj", "{C4AEAB04-F341-4539-B6C0-52368FB4BF9E}"
EndProject
diff --git a/clients/ts/FunctionalTests/ts/ConnectionTests.ts b/clients/ts/FunctionalTests/ts/ConnectionTests.ts
index 58aae5f2da..a2133a26d7 100644
--- a/clients/ts/FunctionalTests/ts/ConnectionTests.ts
+++ b/clients/ts/FunctionalTests/ts/ConnectionTests.ts
@@ -1,15 +1,20 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-import { HttpConnection, LogLevel, TransferFormat, TransportType } from "@aspnet/signalr";
+import { HttpConnection, IHttpConnectionOptions, LogLevel, TransferFormat, TransportType } from "@aspnet/signalr";
import { eachTransport, ECHOENDPOINT_URL } from "./Common";
import { TestLogger } from "./TestLogger";
+const commonOptions: IHttpConnectionOptions = {
+ logMessageContent: true,
+ logger: TestLogger.instance,
+};
+
describe("connection", () => {
it("can connect to the server without specifying transport explicitly", (done) => {
const message = "Hello World!";
const connection = new HttpConnection(ECHOENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
});
let received = "";
@@ -34,33 +39,103 @@ describe("connection", () => {
});
eachTransport((transportType) => {
- it("over " + TransportType[transportType] + " can send and receive messages", (done) => {
- const message = "Hello World!";
- // the url should be resolved relative to the document.location.host
- // and the leading '/' should be automatically added to the url
- const connection = new HttpConnection("echo", {
- logger: TestLogger.instance,
- transport: transportType,
+ describe(`over ${TransportType[transportType]}`, () => {
+ it("can send and receive messages", (done) => {
+ const message = "Hello World!";
+ // the url should be resolved relative to the document.location.host
+ // and the leading '/' should be automatically added to the url
+ const connection = new HttpConnection("echo", {
+ ...commonOptions,
+ transport: transportType,
+ });
+
+ let received = "";
+ connection.onreceive = (data) => {
+ received += data;
+ if (data === message) {
+ connection.stop();
+ }
+ };
+
+ connection.onclose = (error) => {
+ expect(error).toBeUndefined();
+ done();
+ };
+
+ connection.start(TransferFormat.Text).then(() => {
+ connection.send(message);
+ }).catch((e) => {
+ fail(e);
+ done();
+ });
});
- let received = "";
- connection.onreceive = (data) => {
- received += data;
- if (data === message) {
- connection.stop();
- }
- };
+ it("does not log content of messages sent or received by default", (done) => {
+ const message = "Hello World!";
- connection.onclose = (error) => {
- expect(error).toBeUndefined();
- done();
- };
+ // DON'T use commonOptions because we want to specifically test the scenario where logMessageContent is not set.
+ const connection = new HttpConnection("echo", {
+ transport: transportType,
+ });
- connection.start(TransferFormat.Text).then(() => {
- connection.send(message);
- }).catch((e) => {
- fail(e);
- done();
+ connection.onreceive = (data) => {
+ if (data === message) {
+ connection.stop();
+ }
+ };
+
+ connection.onclose = (error) => {
+ // Search the logs for the message content
+ for (const [_, logMessage] of TestLogger.instance.currentLog.messages) {
+ expect(logMessage).not.toContain(message);
+ }
+ done();
+ };
+
+ connection.start(TransferFormat.Text).then(() => {
+ connection.send(message);
+ }).catch((e) => {
+ fail(e);
+ done();
+ });
+ });
+
+ it("does log content of messages sent or received when enabled", (done) => {
+ const message = "Hello World!";
+
+ // DON'T use commonOptions because we want to specifically test the scenario where logMessageContent is set to true (even if commonOptions changes).
+ const connection = new HttpConnection("echo", {
+ logMessageContent: true,
+ logger: TestLogger.instance,
+ transport: transportType,
+ });
+
+ connection.onreceive = (data) => {
+ if (data === message) {
+ connection.stop();
+ }
+ };
+
+ connection.onclose = (error) => {
+ // Search the logs for the message content
+ let matches = 0;
+ for (const [_, logMessage] of TestLogger.instance.currentLog.messages) {
+ if (logMessage.indexOf(message) !== -1) {
+ matches += 1;
+ }
+ }
+
+ // One match for send, one for receive.
+ expect(matches).toEqual(2);
+ done();
+ };
+
+ connection.start(TransferFormat.Text).then(() => {
+ connection.send(message);
+ }).catch((e) => {
+ fail(e);
+ done();
+ });
});
});
});
diff --git a/clients/ts/FunctionalTests/ts/HubConnectionTests.ts b/clients/ts/FunctionalTests/ts/HubConnectionTests.ts
index 2f7a92c51b..0b7fb0f391 100644
--- a/clients/ts/FunctionalTests/ts/HubConnectionTests.ts
+++ b/clients/ts/FunctionalTests/ts/HubConnectionTests.ts
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-import { HubConnection, JsonHubProtocol, LogLevel, TransportType } from "@aspnet/signalr";
+import { HubConnection, IHubConnectionOptions, JsonHubProtocol, LogLevel, TransportType } from "@aspnet/signalr";
import { MessagePackHubProtocol } from "@aspnet/signalr-protocol-msgpack";
import { eachTransport, eachTransportAndProtocol } from "./Common";
@@ -10,6 +10,11 @@ import { TestLogger } from "./TestLogger";
const TESTHUBENDPOINT_URL = "/testhub";
const TESTHUB_NOWEBSOCKETS_ENDPOINT_URL = "/testhub-nowebsockets";
+const commonOptions: IHubConnectionOptions = {
+ logMessageContent: true,
+ logger: TestLogger.instance,
+};
+
describe("hubConnection", () => {
eachTransportAndProtocol((transportType, protocol) => {
describe("using " + protocol.name + " over " + TransportType[transportType] + " transport", () => {
@@ -17,7 +22,7 @@ describe("hubConnection", () => {
const message = "你好,世界!";
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -44,7 +49,7 @@ describe("hubConnection", () => {
const message = "你好,世界!";
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -67,7 +72,7 @@ describe("hubConnection", () => {
it("can invoke server method structural object and receive structural result", (done) => {
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -93,7 +98,7 @@ describe("hubConnection", () => {
it("can stream server method and receive result", (done) => {
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -127,7 +132,7 @@ describe("hubConnection", () => {
it("rethrows an exception from the server when invoking", (done) => {
const errorMessage = "An unexpected error occurred invoking 'ThrowException' on the server. InvalidOperationException: An error occurred.";
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -151,7 +156,7 @@ describe("hubConnection", () => {
it("throws an exception when invoking streaming method with invoke", (done) => {
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -175,7 +180,7 @@ describe("hubConnection", () => {
it("throws an exception when receiving a streaming result for method called with invoke", (done) => {
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -200,7 +205,7 @@ describe("hubConnection", () => {
it("rethrows an exception from the server when streaming", (done) => {
const errorMessage = "An unexpected error occurred invoking 'StreamThrowException' on the server. InvalidOperationException: An error occurred.";
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -229,7 +234,7 @@ describe("hubConnection", () => {
it("throws an exception when invoking hub method with stream", (done) => {
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -258,7 +263,7 @@ describe("hubConnection", () => {
it("can receive server calls", (done) => {
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -290,7 +295,7 @@ describe("hubConnection", () => {
it("can receive server calls without rebinding handler when restarted", (done) => {
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -347,7 +352,7 @@ describe("hubConnection", () => {
it("closed with error if hub cannot be created", (done) => {
const hubConnection = new HubConnection("http://" + document.location.host + "/uncreatable", {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -361,7 +366,7 @@ describe("hubConnection", () => {
it("can handle different types", (done) => {
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -409,7 +414,7 @@ describe("hubConnection", () => {
const message = "你好,世界!";
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol,
transport: transportType,
});
@@ -464,7 +469,7 @@ describe("hubConnection", () => {
const jwtToken = await getJwtToken("http://" + document.location.host + "/generateJwtToken");
const hubConnection = new HubConnection("/authorizedhub", {
accessTokenFactory: () => jwtToken,
- logger: TestLogger.instance,
+ ...commonOptions,
transport: transportType,
});
hubConnection.onclose((error) => {
@@ -488,7 +493,7 @@ describe("hubConnection", () => {
if (transportType !== TransportType.LongPolling) {
it("terminates if no messages received within timeout interval", (done) => {
const hubConnection = new HubConnection(TESTHUBENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
timeoutInMilliseconds: 100,
transport: transportType,
});
@@ -512,7 +517,7 @@ describe("hubConnection", () => {
if (typeof EventSource !== "undefined") {
it("allows Server-Sent Events when negotiating for JSON protocol", async (done) => {
const hubConnection = new HubConnection(TESTHUB_NOWEBSOCKETS_ENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol: new JsonHubProtocol(),
});
@@ -530,7 +535,7 @@ describe("hubConnection", () => {
it("skips Server-Sent Events when negotiating for MsgPack protocol", async (done) => {
const hubConnection = new HubConnection(TESTHUB_NOWEBSOCKETS_ENDPOINT_URL, {
- logger: TestLogger.instance,
+ ...commonOptions,
protocol: new MessagePackHubProtocol(),
});
diff --git a/clients/ts/FunctionalTests/ts/TestLogger.ts b/clients/ts/FunctionalTests/ts/TestLogger.ts
index 1d9e324f60..81ed67ae7d 100644
--- a/clients/ts/FunctionalTests/ts/TestLogger.ts
+++ b/clients/ts/FunctionalTests/ts/TestLogger.ts
@@ -1,22 +1,58 @@
import { ConsoleLogger, ILogger, LogLevel } from "@aspnet/signalr";
+export class TestLog {
+ public messages: Array<[LogLevel, string]> = [];
+
+ public addMessage(logLevel: LogLevel, message: string): void {
+ this.messages.push([logLevel, message]);
+ }
+
+ public getLog(): string {
+ // Dump the logs to a string
+ let str = "";
+ for (const [level, message] of this.messages) {
+ str += `${LogLevel[level]}: ${message}\r\n`;
+ }
+
+ return str;
+ }
+
+ public getLogUrl(): string {
+ const log = this.getLog();
+ return `data:text/plain;base64,${escape(btoa(log))}`;
+ }
+
+ public open(): void {
+ window.open(this.getLogUrl());
+ }
+}
+
export class TestLogger implements ILogger {
public static instance: TestLogger = new TestLogger();
private static consoleLogger: ConsoleLogger = new ConsoleLogger(LogLevel.Trace);
- public messages: Array<[LogLevel, string]> = [];
+ public currentLog: TestLog = new TestLog();
public log(logLevel: LogLevel, message: string): void {
- // Capture log message so it can be reported later
- this.messages.push([logLevel, message]);
+ this.currentLog.addMessage(logLevel, message);
// Also write to browser console
TestLogger.consoleLogger.log(logLevel, message);
}
- public static getMessagesAndReset(): Array<[LogLevel, string]> {
- const messages = TestLogger.instance.messages;
- TestLogger.instance = new TestLogger();
- return messages;
+ public static saveLogsAndReset(testName: string): TestLog {
+ const currentLog = TestLogger.instance.currentLog;
+
+ // Stash the messages in a global to help people review them
+ if (window) {
+ const win = window as any;
+ if (!win.TestLogMessages) {
+ win.TestLogMessages = {};
+ }
+ win.TestLogMessages[testName] = currentLog;
+ }
+
+ TestLogger.instance.currentLog = new TestLog();
+ return currentLog;
}
}
diff --git a/clients/ts/FunctionalTests/ts/WebDriverReporter.ts b/clients/ts/FunctionalTests/ts/WebDriverReporter.ts
index dc81e8a694..f6449f1f18 100644
--- a/clients/ts/FunctionalTests/ts/WebDriverReporter.ts
+++ b/clients/ts/FunctionalTests/ts/WebDriverReporter.ts
@@ -48,7 +48,7 @@ class WebDriverReporter implements jasmine.CustomReporter {
public specDone(result: jasmine.CustomReporterResult): void {
this.concurrentSpecCount -= 1;
- const messages = TestLogger.getMessagesAndReset();
+ const testLog = TestLogger.saveLogsAndReset(result.fullName);
if (result.status === "disabled") {
return;
} else if (result.status === "failed") {
@@ -74,9 +74,9 @@ class WebDriverReporter implements jasmine.CustomReporter {
}
// Report log messages
- if (messages.length > 0) {
+ if (testLog.messages.length > 0) {
this.taplog(" - logs: ");
- for (const [level, message] of messages) {
+ for (const [level, message] of testLog.messages) {
this.taplog(` - level: ${LogLevel[level]}`);
this.taplog(` message: ${message}`);
}
diff --git a/clients/ts/FunctionalTests/web.config b/clients/ts/FunctionalTests/web.config
index 8700b60c05..5defc1eb37 100644
--- a/clients/ts/FunctionalTests/web.config
+++ b/clients/ts/FunctionalTests/web.config
@@ -7,6 +7,8 @@
-
+
+
+
\ No newline at end of file
diff --git a/clients/ts/signalr/src/HttpConnection.ts b/clients/ts/signalr/src/HttpConnection.ts
index 4efa4867c5..4f6fb08152 100644
--- a/clients/ts/signalr/src/HttpConnection.ts
+++ b/clients/ts/signalr/src/HttpConnection.ts
@@ -14,6 +14,7 @@ export interface IHttpConnectionOptions {
transport?: TransportType | ITransport;
logger?: ILogger | LogLevel;
accessTokenFactory?: () => string;
+ logMessageContent?: boolean;
}
const enum ConnectionState {
@@ -53,6 +54,7 @@ export class HttpConnection implements IConnection {
options = options || {};
options.accessTokenFactory = options.accessTokenFactory || (() => null);
+ options.logMessageContent = options.logMessageContent || false;
this.httpClient = options.httpClient || new DefaultHttpClient(this.logger);
this.connectionState = ConnectionState.Disconnected;
@@ -176,11 +178,11 @@ export class HttpConnection implements IConnection {
private constructTransport(transport: TransportType) {
switch (transport) {
case TransportType.WebSockets:
- return new WebSocketTransport(this.options.accessTokenFactory, this.logger);
+ return new WebSocketTransport(this.options.accessTokenFactory, this.logger, this.options.logMessageContent);
case TransportType.ServerSentEvents:
- return new ServerSentEventsTransport(this.httpClient, this.options.accessTokenFactory, this.logger);
+ return new ServerSentEventsTransport(this.httpClient, this.options.accessTokenFactory, this.logger, this.options.logMessageContent);
case TransportType.LongPolling:
- return new LongPollingTransport(this.httpClient, this.options.accessTokenFactory, this.logger);
+ return new LongPollingTransport(this.httpClient, this.options.accessTokenFactory, this.logger, this.options.logMessageContent);
default:
throw new Error(`Unknown transport: ${transport}.`);
}
diff --git a/clients/ts/signalr/src/Transports.ts b/clients/ts/signalr/src/Transports.ts
index 7e142019bd..0d8a79d8da 100644
--- a/clients/ts/signalr/src/Transports.ts
+++ b/clients/ts/signalr/src/Transports.ts
@@ -31,11 +31,13 @@ export interface ITransport {
export class WebSocketTransport implements ITransport {
private readonly logger: ILogger;
private readonly accessTokenFactory: () => string;
+ private readonly logMessageContent: boolean;
private webSocket: WebSocket;
- constructor(accessTokenFactory: () => string, logger: ILogger) {
+ constructor(accessTokenFactory: () => string, logger: ILogger, logMessageContent: boolean) {
this.logger = logger;
this.accessTokenFactory = accessTokenFactory || (() => null);
+ this.logMessageContent = logMessageContent;
}
public connect(url: string, transferFormat: TransferFormat, connection: IConnection): Promise {
@@ -73,7 +75,7 @@ export class WebSocketTransport implements ITransport {
};
webSocket.onmessage = (message: MessageEvent) => {
- this.logger.log(LogLevel.Trace, `(WebSockets transport) data received. ${getDataDetail(message.data)}.`);
+ this.logger.log(LogLevel.Trace, `(WebSockets transport) data received. ${getDataDetail(message.data, this.logMessageContent)}.`);
if (this.onreceive) {
this.onreceive(message.data);
}
@@ -94,7 +96,7 @@ export class WebSocketTransport implements ITransport {
public send(data: any): Promise {
if (this.webSocket && this.webSocket.readyState === WebSocket.OPEN) {
- this.logger.log(LogLevel.Trace, `(WebSockets transport) sending data. ${getDataDetail(data)}.`);
+ this.logger.log(LogLevel.Trace, `(WebSockets transport) sending data. ${getDataDetail(data, this.logMessageContent)}.`);
this.webSocket.send(data);
return Promise.resolve();
}
@@ -118,13 +120,15 @@ export class ServerSentEventsTransport implements ITransport {
private readonly httpClient: HttpClient;
private readonly accessTokenFactory: () => string;
private readonly logger: ILogger;
+ private readonly logMessageContent: boolean;
private eventSource: EventSource;
private url: string;
- constructor(httpClient: HttpClient, accessTokenFactory: () => string, logger: ILogger) {
+ constructor(httpClient: HttpClient, accessTokenFactory: () => string, logger: ILogger, logMessageContent: boolean) {
this.httpClient = httpClient;
this.accessTokenFactory = accessTokenFactory || (() => null);
this.logger = logger;
+ this.logMessageContent = logMessageContent;
}
public connect(url: string, transferFormat: TransferFormat, connection: IConnection): Promise {
@@ -156,7 +160,7 @@ export class ServerSentEventsTransport implements ITransport {
eventSource.onmessage = (e: MessageEvent) => {
if (this.onreceive) {
try {
- this.logger.log(LogLevel.Trace, `(SSE transport) data received. ${getDataDetail(e.data)}.`);
+ this.logger.log(LogLevel.Trace, `(SSE transport) data received. ${getDataDetail(e.data, this.logMessageContent)}.`);
this.onreceive(e.data);
} catch (error) {
if (this.onclose) {
@@ -189,7 +193,7 @@ export class ServerSentEventsTransport implements ITransport {
}
public async send(data: any): Promise {
- return send(this.logger, "SSE", this.httpClient, this.url, this.accessTokenFactory, data);
+ return send(this.logger, "SSE", this.httpClient, this.url, this.accessTokenFactory, data, this.logMessageContent);
}
public stop(): Promise {
@@ -208,16 +212,18 @@ export class LongPollingTransport implements ITransport {
private readonly httpClient: HttpClient;
private readonly accessTokenFactory: () => string;
private readonly logger: ILogger;
+ private readonly logMessageContent: boolean;
private url: string;
private pollXhr: XMLHttpRequest;
private pollAbort: AbortController;
- constructor(httpClient: HttpClient, accessTokenFactory: () => string, logger: ILogger) {
+ constructor(httpClient: HttpClient, accessTokenFactory: () => string, logger: ILogger, logMessageContent: boolean) {
this.httpClient = httpClient;
this.accessTokenFactory = accessTokenFactory || (() => null);
this.logger = logger;
this.pollAbort = new AbortController();
+ this.logMessageContent = logMessageContent;
}
public connect(url: string, transferFormat: TransferFormat, connection: IConnection): Promise {
@@ -283,7 +289,7 @@ export class LongPollingTransport implements ITransport {
} else {
// Process the response
if (response.content) {
- this.logger.log(LogLevel.Trace, `(LongPolling transport) data received. ${getDataDetail(response.content)}.`);
+ this.logger.log(LogLevel.Trace, `(LongPolling transport) data received. ${getDataDetail(response.content, this.logMessageContent)}`);
if (this.onreceive) {
this.onreceive(response.content);
}
@@ -308,7 +314,7 @@ export class LongPollingTransport implements ITransport {
}
public async send(data: any): Promise {
- return send(this.logger, "LongPolling", this.httpClient, this.url, this.accessTokenFactory, data);
+ return send(this.logger, "LongPolling", this.httpClient, this.url, this.accessTokenFactory, data, this.logMessageContent);
}
public stop(): Promise {
@@ -320,17 +326,37 @@ export class LongPollingTransport implements ITransport {
public onclose: TransportClosed;
}
-function getDataDetail(data: any): string {
+function getDataDetail(data: any, includeContent: boolean): string {
let length: string = null;
if (data instanceof ArrayBuffer) {
- length = `Binary data of length ${data.byteLength}`;
+ length = `Binary data of length ${data.byteLength}.`;
+ if (includeContent) {
+ length += ` Content: '${formatArrayBuffer(data)}'.`;
+ }
} else if (typeof data === "string") {
- length = `String data of length ${data.length}`;
+ length = `String data of length ${data.length}.`;
+ if (includeContent) {
+ length += ` Content: '${data}'.`;
+ }
}
return length;
}
-async function send(logger: ILogger, transportName: string, httpClient: HttpClient, url: string, accessTokenFactory: () => string, content: string | ArrayBuffer): Promise {
+function formatArrayBuffer(data: ArrayBuffer): string {
+ const view = new Uint8Array(data);
+
+ // Uint8Array.map only supports returning another Uint8Array?
+ let str = "";
+ view.forEach((num) => {
+ const pad = num < 16 ? "0" : "";
+ str += `0x${pad}${num.toString(16)} `;
+ });
+
+ // Trim of trailing space.
+ return str.substr(0, str.length - 1);
+}
+
+async function send(logger: ILogger, transportName: string, httpClient: HttpClient, url: string, accessTokenFactory: () => string, content: string | ArrayBuffer, logMessageContent: boolean): Promise {
let headers;
const token = accessTokenFactory();
if (token) {
@@ -339,7 +365,7 @@ async function send(logger: ILogger, transportName: string, httpClient: HttpClie
};
}
- logger.log(LogLevel.Trace, `(${transportName} transport) sending data. ${getDataDetail(content)}.`);
+ logger.log(LogLevel.Trace, `(${transportName} transport) sending data. ${getDataDetail(content, logMessageContent)}.`);
const response = await httpClient.post(url, {
content,