Returning rejected promises in HttpConnection (#8315)
This commit is contained in:
parent
c9c2bf6ea5
commit
96764d27eb
|
|
@ -115,7 +115,7 @@ export class HttpConnection implements IConnection {
|
||||||
|
|
||||||
public send(data: string | ArrayBuffer): Promise<void> {
|
public send(data: string | ArrayBuffer): Promise<void> {
|
||||||
if (this.connectionState !== ConnectionState.Connected) {
|
if (this.connectionState !== ConnectionState.Connected) {
|
||||||
throw new Error("Cannot send data if the connection is not in the 'Connected' State.");
|
return Promise.reject(new Error("Cannot send data if the connection is not in the 'Connected' State."));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transport will not be null if state is connected
|
// Transport will not be null if state is connected
|
||||||
|
|
@ -157,7 +157,7 @@ export class HttpConnection implements IConnection {
|
||||||
// No fallback or negotiate in this case.
|
// No fallback or negotiate in this case.
|
||||||
await this.transport!.connect(url, transferFormat);
|
await this.transport!.connect(url, transferFormat);
|
||||||
} else {
|
} else {
|
||||||
throw Error("Negotiation can only be skipped when using the WebSocket transport directly.");
|
return Promise.reject(new Error("Negotiation can only be skipped when using the WebSocket transport directly."));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let negotiateResponse: INegotiateResponse | null = null;
|
let negotiateResponse: INegotiateResponse | null = null;
|
||||||
|
|
@ -171,11 +171,11 @@ export class HttpConnection implements IConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (negotiateResponse.error) {
|
if (negotiateResponse.error) {
|
||||||
throw Error(negotiateResponse.error);
|
return Promise.reject(new Error(negotiateResponse.error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((negotiateResponse as any).ProtocolVersion) {
|
if ((negotiateResponse as any).ProtocolVersion) {
|
||||||
throw Error("Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.");
|
return Promise.reject(new Error("Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (negotiateResponse.url) {
|
if (negotiateResponse.url) {
|
||||||
|
|
@ -194,7 +194,7 @@ export class HttpConnection implements IConnection {
|
||||||
while (negotiateResponse.url && redirects < MAX_REDIRECTS);
|
while (negotiateResponse.url && redirects < MAX_REDIRECTS);
|
||||||
|
|
||||||
if (redirects === MAX_REDIRECTS && negotiateResponse.url) {
|
if (redirects === MAX_REDIRECTS && negotiateResponse.url) {
|
||||||
throw Error("Negotiate redirection limit exceeded.");
|
return Promise.reject(new Error("Negotiate redirection limit exceeded."));
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.createTransport(url, this.options.transport, negotiateResponse, transferFormat);
|
await this.createTransport(url, this.options.transport, negotiateResponse, transferFormat);
|
||||||
|
|
@ -214,7 +214,7 @@ export class HttpConnection implements IConnection {
|
||||||
this.logger.log(LogLevel.Error, "Failed to start the connection: " + e);
|
this.logger.log(LogLevel.Error, "Failed to start the connection: " + e);
|
||||||
this.connectionState = ConnectionState.Disconnected;
|
this.connectionState = ConnectionState.Disconnected;
|
||||||
this.transport = undefined;
|
this.transport = undefined;
|
||||||
throw e;
|
return Promise.reject(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,13 +238,13 @@ export class HttpConnection implements IConnection {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.statusCode !== 200) {
|
if (response.statusCode !== 200) {
|
||||||
throw Error(`Unexpected status code returned from negotiate ${response.statusCode}`);
|
return Promise.reject(new Error(`Unexpected status code returned from negotiate ${response.statusCode}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.parse(response.content as string) as INegotiateResponse;
|
return JSON.parse(response.content as string) as INegotiateResponse;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.log(LogLevel.Error, "Failed to complete negotiation with the server: " + e);
|
this.logger.log(LogLevel.Error, "Failed to complete negotiation with the server: " + e);
|
||||||
throw e;
|
return Promise.reject(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -293,9 +293,9 @@ export class HttpConnection implements IConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transportExceptions.length > 0) {
|
if (transportExceptions.length > 0) {
|
||||||
throw new Error(`Unable to connect to the server with any of the available transports. ${transportExceptions.join(" ")}`);
|
return Promise.reject(new Error(`Unable to connect to the server with any of the available transports. ${transportExceptions.join(" ")}`));
|
||||||
}
|
}
|
||||||
throw new Error("None of the transports supported by the client are supported by the server.");
|
return Promise.reject(new Error("None of the transports supported by the client are supported by the server."));
|
||||||
}
|
}
|
||||||
|
|
||||||
private constructTransport(transport: HttpTransportType) {
|
private constructTransport(transport: HttpTransportType) {
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,72 @@ describe("HttpConnection", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("cannot send with an un-started connection", async () => {
|
||||||
|
await VerifyLogger.run(async (logger) => {
|
||||||
|
const connection = new HttpConnection("http://tempuri.org");
|
||||||
|
|
||||||
|
await expect(connection.send("LeBron James"))
|
||||||
|
.rejects
|
||||||
|
.toThrow("Cannot send data if the connection is not in the 'Connected' State.");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sending before start doesn't throw synchronously", async () => {
|
||||||
|
await VerifyLogger.run(async (logger) => {
|
||||||
|
const connection = new HttpConnection("http://tempuri.org");
|
||||||
|
|
||||||
|
try {
|
||||||
|
connection.send("test").catch((e) => {});
|
||||||
|
} catch (e) {
|
||||||
|
expect(false).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("cannot be started if negotiate returns non 200 response", async () => {
|
||||||
|
await VerifyLogger.run(async (logger) => {
|
||||||
|
const options: IHttpConnectionOptions = {
|
||||||
|
...commonOptions,
|
||||||
|
httpClient: new TestHttpClient()
|
||||||
|
.on("POST", () => new HttpResponse(999))
|
||||||
|
.on("GET", () => ""),
|
||||||
|
logger,
|
||||||
|
} as IHttpConnectionOptions;
|
||||||
|
|
||||||
|
const connection = new HttpConnection("http://tempuri.org", options);
|
||||||
|
await expect(connection.start(TransferFormat.Text))
|
||||||
|
.rejects
|
||||||
|
.toThrow("Unexpected status code returned from negotiate 999");
|
||||||
|
},
|
||||||
|
"Failed to start the connection: Error: Unexpected status code returned from negotiate 999");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("all transport failure error get aggregated", async () => {
|
||||||
|
await VerifyLogger.run(async (loggerImpl) => {
|
||||||
|
const options: IHttpConnectionOptions = {
|
||||||
|
WebSocket: false,
|
||||||
|
...commonOptions,
|
||||||
|
httpClient: new TestHttpClient()
|
||||||
|
.on("POST", () => defaultNegotiateResponse)
|
||||||
|
.on("GET", () => new HttpResponse(200))
|
||||||
|
.on("DELETE", () => new HttpResponse(202)),
|
||||||
|
|
||||||
|
logger: loggerImpl,
|
||||||
|
transport: HttpTransportType.WebSockets,
|
||||||
|
} as IHttpConnectionOptions;
|
||||||
|
|
||||||
|
const connection = new HttpConnection("http://tempuri.org", options);
|
||||||
|
await expect(connection.start(TransferFormat.Text))
|
||||||
|
.rejects
|
||||||
|
.toThrow("Unable to connect to the server with any of the available transports. WebSockets failed: null ServerSentEvents failed: Error: 'ServerSentEvents' is disabled by the client. LongPolling failed: Error: 'LongPolling' is disabled by the client.");
|
||||||
|
},
|
||||||
|
"Failed to start the transport 'WebSockets': null",
|
||||||
|
"Failed to start the transport 'ServerSentEvents': Error: 'ServerSentEvents' is disabled by the client.",
|
||||||
|
"Failed to start the transport 'LongPolling': Error: 'LongPolling' is disabled by the client.",
|
||||||
|
"Failed to start the connection: Error: Unable to connect to the server with any of the available transports. WebSockets failed: null ServerSentEvents failed: Error: 'ServerSentEvents' is disabled by the client. LongPolling failed: Error: 'LongPolling' is disabled by the client.");
|
||||||
|
});
|
||||||
|
|
||||||
it("can stop a non-started connection", async () => {
|
it("can stop a non-started connection", async () => {
|
||||||
await VerifyLogger.run(async (logger) => {
|
await VerifyLogger.run(async (logger) => {
|
||||||
const connection = new HttpConnection("http://tempuri.org", { ...commonOptions, logger });
|
const connection = new HttpConnection("http://tempuri.org", { ...commonOptions, logger });
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue