Merge pull request #3250 from dotnet-maestro-bot/merge/release/2.2-to-master
[automated] Merge branch 'release/2.2' => 'master'
This commit is contained in:
commit
b2037efa08
|
|
@ -328,7 +328,7 @@ public class HubConnection {
|
||||||
sendHubMessage(PingMessage.getInstance());
|
sendHubMessage(PingMessage.getInstance());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn(String.format("Error sending ping: {}", e.getMessage()));
|
logger.warn("Error sending ping: {}.", e.getMessage());
|
||||||
// The connection is probably in a bad or closed state now, cleanup the timer so
|
// The connection is probably in a bad or closed state now, cleanup the timer so
|
||||||
// it stops triggering
|
// it stops triggering
|
||||||
pingTimer.cancel();
|
pingTimer.cancel();
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ class OkHttpWebSocketWrapper extends WebSocketWrapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
||||||
logger.error("Websocket closed from an error: {}.", t.getMessage());
|
logger.error("WebSocket closed from an error: {}.", t.getMessage());
|
||||||
closeSubject.onError(new RuntimeException(t));
|
closeSubject.onError(new RuntimeException(t));
|
||||||
onClose.invoke(null, t.getMessage());
|
onClose.invoke(null, t.getMessage());
|
||||||
checkStartFailure();
|
checkStartFailure();
|
||||||
|
|
@ -103,10 +103,8 @@ class OkHttpWebSocketWrapper extends WebSocketWrapper {
|
||||||
// If the start task hasn't completed yet, then we need to complete it
|
// If the start task hasn't completed yet, then we need to complete it
|
||||||
// exceptionally.
|
// exceptionally.
|
||||||
if (!startSubject.hasComplete()) {
|
if (!startSubject.hasComplete()) {
|
||||||
String errorMessage = "There was an error starting the Websockets transport.";
|
startSubject.onError(new RuntimeException("There was an error starting the WebSocket transport."));
|
||||||
logger.error("Websocket closed from an error: {}.", errorMessage);
|
|
||||||
startSubject.onError(new RuntimeException(errorMessage));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@ import io.reactivex.Single;
|
||||||
|
|
||||||
class WebSocketTransportTest {
|
class WebSocketTransportTest {
|
||||||
@Test
|
@Test
|
||||||
public void WebsocketThrowsIfItCantConnect() {
|
public void WebSocketThrowsIfItCantConnect() {
|
||||||
Transport transport = new WebSocketTransport(new HashMap<>(), new DefaultHttpClient());
|
Transport transport = new WebSocketTransport(new HashMap<>(), new DefaultHttpClient());
|
||||||
RuntimeException exception = assertThrows(RuntimeException.class, () -> transport.start("http://www.example.com").blockingAwait(1, TimeUnit.SECONDS));
|
RuntimeException exception = assertThrows(RuntimeException.class, () -> transport.start("http://url.fake.example").blockingAwait(1, TimeUnit.SECONDS));
|
||||||
assertEquals("There was an error starting the Websockets transport.", exception.getMessage());
|
assertEquals("There was an error starting the WebSocket transport.", exception.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ export class HttpConnection implements IConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
const negotiateUrl = this.resolveNegotiateUrl(url);
|
const negotiateUrl = this.resolveNegotiateUrl(url);
|
||||||
this.logger.log(LogLevel.Debug, `Sending negotiation request: ${negotiateUrl}`);
|
this.logger.log(LogLevel.Debug, `Sending negotiation request: ${negotiateUrl}.`);
|
||||||
try {
|
try {
|
||||||
const response = await this.httpClient.post(negotiateUrl, {
|
const response = await this.httpClient.post(negotiateUrl, {
|
||||||
content: "",
|
content: "",
|
||||||
|
|
@ -324,7 +324,7 @@ export class HttpConnection implements IConnection {
|
||||||
(transport === HttpTransportType.ServerSentEvents && !this.options.EventSource)) {
|
(transport === HttpTransportType.ServerSentEvents && !this.options.EventSource)) {
|
||||||
this.logger.log(LogLevel.Debug, `Skipping transport '${HttpTransportType[transport]}' because it is not supported in your environment.'`);
|
this.logger.log(LogLevel.Debug, `Skipping transport '${HttpTransportType[transport]}' because it is not supported in your environment.'`);
|
||||||
} else {
|
} else {
|
||||||
this.logger.log(LogLevel.Debug, `Selecting transport '${HttpTransportType[transport]}'`);
|
this.logger.log(LogLevel.Debug, `Selecting transport '${HttpTransportType[transport]}'.`);
|
||||||
return transport;
|
return transport;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -373,7 +373,7 @@ export class HubConnection {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.logger.log(LogLevel.Warning, "Invalid message type: " + message.type);
|
this.logger.log(LogLevel.Warning, `Invalid message type: ${message.type}.`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ export class LongPollingTransport implements ITransport {
|
||||||
|
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
|
||||||
this.logger.log(LogLevel.Trace, "(LongPolling transport) Connecting");
|
this.logger.log(LogLevel.Trace, "(LongPolling transport) Connecting.");
|
||||||
|
|
||||||
// Allow binary format on Node and Browsers that support binary content (indicated by the presence of responseType property)
|
// Allow binary format on Node and Browsers that support binary content (indicated by the presence of responseType property)
|
||||||
if (transferFormat === TransferFormat.Binary &&
|
if (transferFormat === TransferFormat.Binary &&
|
||||||
|
|
@ -74,10 +74,10 @@ export class LongPollingTransport implements ITransport {
|
||||||
// Make initial long polling request
|
// Make initial long polling request
|
||||||
// Server uses first long polling request to finish initializing connection and it returns without data
|
// Server uses first long polling request to finish initializing connection and it returns without data
|
||||||
const pollUrl = `${url}&_=${Date.now()}`;
|
const pollUrl = `${url}&_=${Date.now()}`;
|
||||||
this.logger.log(LogLevel.Trace, `(LongPolling transport) polling: ${pollUrl}`);
|
this.logger.log(LogLevel.Trace, `(LongPolling transport) polling: ${pollUrl}.`);
|
||||||
const response = await this.httpClient.get(pollUrl, pollOptions);
|
const response = await this.httpClient.get(pollUrl, pollOptions);
|
||||||
if (response.statusCode !== 200) {
|
if (response.statusCode !== 200) {
|
||||||
this.logger.log(LogLevel.Error, `(LongPolling transport) Unexpected response code: ${response.statusCode}`);
|
this.logger.log(LogLevel.Error, `(LongPolling transport) Unexpected response code: ${response.statusCode}.`);
|
||||||
|
|
||||||
// Mark running as false so that the poll immediately ends and runs the close logic
|
// Mark running as false so that the poll immediately ends and runs the close logic
|
||||||
this.closeError = new HttpError(response.statusText || "", response.statusCode);
|
this.closeError = new HttpError(response.statusText || "", response.statusCode);
|
||||||
|
|
@ -122,15 +122,15 @@ export class LongPollingTransport implements ITransport {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const pollUrl = `${url}&_=${Date.now()}`;
|
const pollUrl = `${url}&_=${Date.now()}`;
|
||||||
this.logger.log(LogLevel.Trace, `(LongPolling transport) polling: ${pollUrl}`);
|
this.logger.log(LogLevel.Trace, `(LongPolling transport) polling: ${pollUrl}.`);
|
||||||
const response = await this.httpClient.get(pollUrl, pollOptions);
|
const response = await this.httpClient.get(pollUrl, pollOptions);
|
||||||
|
|
||||||
if (response.statusCode === 204) {
|
if (response.statusCode === 204) {
|
||||||
this.logger.log(LogLevel.Information, "(LongPolling transport) Poll terminated by server");
|
this.logger.log(LogLevel.Information, "(LongPolling transport) Poll terminated by server.");
|
||||||
|
|
||||||
this.running = false;
|
this.running = false;
|
||||||
} else if (response.statusCode !== 200) {
|
} else if (response.statusCode !== 200) {
|
||||||
this.logger.log(LogLevel.Error, `(LongPolling transport) Unexpected response code: ${response.statusCode}`);
|
this.logger.log(LogLevel.Error, `(LongPolling transport) Unexpected response code: ${response.statusCode}.`);
|
||||||
|
|
||||||
// Unexpected status code
|
// Unexpected status code
|
||||||
this.closeError = new HttpError(response.statusText || "", response.statusCode);
|
this.closeError = new HttpError(response.statusText || "", response.statusCode);
|
||||||
|
|
@ -138,7 +138,7 @@ export class LongPollingTransport implements ITransport {
|
||||||
} else {
|
} else {
|
||||||
// Process the response
|
// Process the response
|
||||||
if (response.content) {
|
if (response.content) {
|
||||||
this.logger.log(LogLevel.Trace, `(LongPolling transport) data received. ${getDataDetail(response.content, this.logMessageContent)}`);
|
this.logger.log(LogLevel.Trace, `(LongPolling transport) data received. ${getDataDetail(response.content, this.logMessageContent)}.`);
|
||||||
if (this.onreceive) {
|
if (this.onreceive) {
|
||||||
this.onreceive(response.content);
|
this.onreceive(response.content);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ export class ServerSentEventsTransport implements ITransport {
|
||||||
Arg.isRequired(transferFormat, "transferFormat");
|
Arg.isRequired(transferFormat, "transferFormat");
|
||||||
Arg.isIn(transferFormat, TransferFormat, "transferFormat");
|
Arg.isIn(transferFormat, TransferFormat, "transferFormat");
|
||||||
|
|
||||||
this.logger.log(LogLevel.Trace, "(SSE transport) Connecting");
|
this.logger.log(LogLevel.Trace, "(SSE transport) Connecting.");
|
||||||
|
|
||||||
// set url before accessTokenFactory because this.url is only for send and we set the auth header instead of the query string for send
|
// set url before accessTokenFactory because this.url is only for send and we set the auth header instead of the query string for send
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export function getDataDetail(data: any, includeContent: boolean): string {
|
||||||
} else if (typeof data === "string") {
|
} else if (typeof data === "string") {
|
||||||
detail = `String data of length ${data.length}`;
|
detail = `String data of length ${data.length}`;
|
||||||
if (includeContent) {
|
if (includeContent) {
|
||||||
detail += `. Content: '${data}'.`;
|
detail += `. Content: '${data}'`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return detail;
|
return detail;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ export class WebSocketTransport implements ITransport {
|
||||||
Arg.isRequired(transferFormat, "transferFormat");
|
Arg.isRequired(transferFormat, "transferFormat");
|
||||||
Arg.isIn(transferFormat, TransferFormat, "transferFormat");
|
Arg.isIn(transferFormat, TransferFormat, "transferFormat");
|
||||||
|
|
||||||
this.logger.log(LogLevel.Trace, "(WebSockets transport) Connecting");
|
this.logger.log(LogLevel.Trace, "(WebSockets transport) Connecting.");
|
||||||
|
|
||||||
if (this.accessTokenFactory) {
|
if (this.accessTokenFactory) {
|
||||||
const token = await this.accessTokenFactory();
|
const token = await this.accessTokenFactory();
|
||||||
|
|
@ -70,7 +70,7 @@ export class WebSocketTransport implements ITransport {
|
||||||
|
|
||||||
// tslint:disable-next-line:variable-name
|
// tslint:disable-next-line:variable-name
|
||||||
webSocket.onopen = (_event: Event) => {
|
webSocket.onopen = (_event: Event) => {
|
||||||
this.logger.log(LogLevel.Information, `WebSocket connected to ${url}`);
|
this.logger.log(LogLevel.Information, `WebSocket connected to ${url}.`);
|
||||||
this.webSocket = webSocket;
|
this.webSocket = webSocket;
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
|
|
@ -127,7 +127,7 @@ export class WebSocketTransport implements ITransport {
|
||||||
this.logger.log(LogLevel.Trace, "(WebSockets transport) socket closed.");
|
this.logger.log(LogLevel.Trace, "(WebSockets transport) socket closed.");
|
||||||
if (this.onclose) {
|
if (this.onclose) {
|
||||||
if (event && (event.wasClean === false || event.code !== 1000)) {
|
if (event && (event.wasClean === false || event.code !== 1000)) {
|
||||||
this.onclose(new Error(`Websocket closed with status code: ${event.code} (${event.reason})`));
|
this.onclose(new Error(`WebSocket closed with status code: ${event.code} (${event.reason}).`));
|
||||||
} else {
|
} else {
|
||||||
this.onclose();
|
this.onclose();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ export class XhrHttpClient extends HttpClient {
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.onerror = () => {
|
xhr.onerror = () => {
|
||||||
this.logger.log(LogLevel.Warning, `Error from HTTP request. ${xhr.status}: ${xhr.statusText}`);
|
this.logger.log(LogLevel.Warning, `Error from HTTP request. ${xhr.status}: ${xhr.statusText}.`);
|
||||||
reject(new HttpError(xhr.statusText, xhr.status));
|
reject(new HttpError(xhr.statusText, xhr.status));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ describe("HttpConnection", () => {
|
||||||
...commonOptions,
|
...commonOptions,
|
||||||
httpClient: new TestHttpClient()
|
httpClient: new TestHttpClient()
|
||||||
.on("POST", () => {
|
.on("POST", () => {
|
||||||
return Promise.reject("reached negotiate");
|
return Promise.reject("reached negotiate.");
|
||||||
})
|
})
|
||||||
.on("GET", () => ""),
|
.on("GET", () => ""),
|
||||||
logger,
|
logger,
|
||||||
|
|
@ -118,14 +118,14 @@ describe("HttpConnection", () => {
|
||||||
|
|
||||||
await expect(connection.start(TransferFormat.Text))
|
await expect(connection.start(TransferFormat.Text))
|
||||||
.rejects
|
.rejects
|
||||||
.toBe("reached negotiate");
|
.toBe("reached negotiate.");
|
||||||
|
|
||||||
await expect(connection.start(TransferFormat.Text))
|
await expect(connection.start(TransferFormat.Text))
|
||||||
.rejects
|
.rejects
|
||||||
.toBe("reached negotiate");
|
.toBe("reached negotiate.");
|
||||||
},
|
},
|
||||||
"Failed to complete negotiation with the server: reached negotiate",
|
"Failed to complete negotiation with the server: reached negotiate.",
|
||||||
"Failed to start the connection: reached negotiate");
|
"Failed to start the connection: reached negotiate.");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("can stop a starting connection", async () => {
|
it("can stop a starting connection", async () => {
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ describe("WebSocketTransport", () => {
|
||||||
TestWebSocket.webSocket.onclose(message);
|
TestWebSocket.webSocket.onclose(message);
|
||||||
|
|
||||||
expect(closeCalled).toBe(true);
|
expect(closeCalled).toBe(true);
|
||||||
expect(error!).toEqual(new Error("Websocket closed with status code: 1 (just cause)"));
|
expect(error!).toEqual(new Error("WebSocket closed with status code: 1 (just cause)."));
|
||||||
|
|
||||||
await expect(webSocket.send(""))
|
await expect(webSocket.send(""))
|
||||||
.rejects
|
.rejects
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue