Decouple IConnection.ts and HubConnection.ts from http (#566)
* Decouple IConnection.ts and HubConnection.ts from http - Removed TransportType from start - Renamed Connection.ts to HttpConnection.ts
This commit is contained in:
parent
0298868c00
commit
d169b96d2d
|
|
@ -1,6 +1,6 @@
|
|||
import { IHttpClient } from "../Microsoft.AspNetCore.SignalR.Client.TS/HttpClient"
|
||||
import { Connection } from "../Microsoft.AspNetCore.SignalR.Client.TS/Connection"
|
||||
import { ISignalROptions } from "../Microsoft.AspNetCore.SignalR.Client.TS/ISignalROptions"
|
||||
import { HttpConnection } from "../Microsoft.AspNetCore.SignalR.Client.TS/HttpConnection"
|
||||
import { IHttpConnectionOptions } from "../Microsoft.AspNetCore.SignalR.Client.TS/IHttpConnectionOptions"
|
||||
import { DataReceived, TransportClosed } from "../Microsoft.AspNetCore.SignalR.Client.TS/Common"
|
||||
import { ITransport, TransportType } from "../Microsoft.AspNetCore.SignalR.Client.TS/Transports"
|
||||
import { eachTransport } from "./Common";
|
||||
|
|
@ -8,7 +8,7 @@ import { eachTransport } from "./Common";
|
|||
describe("Connection", () => {
|
||||
|
||||
it("starting connection fails if getting id fails", async (done) => {
|
||||
let options: ISignalROptions = {
|
||||
let options: IHttpConnectionOptions = {
|
||||
httpClient: <IHttpClient>{
|
||||
options(url: string): Promise<string> {
|
||||
return Promise.reject("error");
|
||||
|
|
@ -17,9 +17,9 @@ describe("Connection", () => {
|
|||
return Promise.resolve("");
|
||||
}
|
||||
}
|
||||
} as ISignalROptions;
|
||||
} as IHttpConnectionOptions;
|
||||
|
||||
let connection = new Connection("http://tempuri.org", options);
|
||||
let connection = new HttpConnection("http://tempuri.org", options);
|
||||
|
||||
try {
|
||||
await connection.start();
|
||||
|
|
@ -33,28 +33,28 @@ describe("Connection", () => {
|
|||
});
|
||||
|
||||
it("cannot start a running connection", async (done) => {
|
||||
let options: ISignalROptions = {
|
||||
let options: IHttpConnectionOptions = {
|
||||
httpClient: <IHttpClient>{
|
||||
options(url: string): Promise<string> {
|
||||
connection.start()
|
||||
.then(() => {
|
||||
fail();
|
||||
done();
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
expect(error.message).toBe("Cannot start a connection that is not in the 'Initial' state.");
|
||||
done();
|
||||
});
|
||||
.then(() => {
|
||||
fail();
|
||||
done();
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
expect(error.message).toBe("Cannot start a connection that is not in the 'Initial' state.");
|
||||
done();
|
||||
});
|
||||
|
||||
return Promise.reject("error");
|
||||
return Promise.reject("error");
|
||||
},
|
||||
get(url: string): Promise<string> {
|
||||
return Promise.resolve("");
|
||||
}
|
||||
}
|
||||
} as ISignalROptions;
|
||||
} as IHttpConnectionOptions;
|
||||
|
||||
let connection = new Connection("http://tempuri.org", options);
|
||||
let connection = new HttpConnection("http://tempuri.org", options);
|
||||
|
||||
try {
|
||||
await connection.start();
|
||||
|
|
@ -66,7 +66,7 @@ describe("Connection", () => {
|
|||
});
|
||||
|
||||
it("cannot start a stopped connection", async (done) => {
|
||||
let options: ISignalROptions = {
|
||||
let options: IHttpConnectionOptions = {
|
||||
httpClient: <IHttpClient>{
|
||||
options(url: string): Promise<string> {
|
||||
return Promise.reject("error");
|
||||
|
|
@ -75,9 +75,9 @@ describe("Connection", () => {
|
|||
return Promise.resolve("");
|
||||
}
|
||||
}
|
||||
} as ISignalROptions;
|
||||
} as IHttpConnectionOptions;
|
||||
|
||||
let connection = new Connection("http://tempuri.org", options);
|
||||
let connection = new HttpConnection("http://tempuri.org", options);
|
||||
|
||||
try {
|
||||
// start will fail and transition the connection to the Disconnected state
|
||||
|
|
@ -99,7 +99,7 @@ describe("Connection", () => {
|
|||
});
|
||||
|
||||
it("can stop a starting connection", async (done) => {
|
||||
let options: ISignalROptions = {
|
||||
let options: IHttpConnectionOptions = {
|
||||
httpClient: <IHttpClient>{
|
||||
options(url: string): Promise<string> {
|
||||
connection.stop();
|
||||
|
|
@ -110,9 +110,9 @@ describe("Connection", () => {
|
|||
return Promise.resolve("");
|
||||
}
|
||||
}
|
||||
} as ISignalROptions;
|
||||
} as IHttpConnectionOptions;
|
||||
|
||||
var connection = new Connection("http://tempuri.org", options);
|
||||
var connection = new HttpConnection("http://tempuri.org", options);
|
||||
|
||||
try {
|
||||
await connection.start();
|
||||
|
|
@ -125,23 +125,12 @@ describe("Connection", () => {
|
|||
});
|
||||
|
||||
it("can stop a non-started connection", async (done) => {
|
||||
var connection = new Connection("http://tempuri.org");
|
||||
var connection = new HttpConnection("http://tempuri.org");
|
||||
await connection.stop();
|
||||
done();
|
||||
});
|
||||
|
||||
it("preserves users connection string", async done => {
|
||||
let options: ISignalROptions = {
|
||||
httpClient: <IHttpClient>{
|
||||
options(url: string): Promise<string> {
|
||||
return Promise.resolve("{ \"connectionId\": \"42\" }");
|
||||
},
|
||||
get(url: string): Promise<string> {
|
||||
return Promise.resolve("");
|
||||
}
|
||||
}
|
||||
} as ISignalROptions;
|
||||
|
||||
let connectUrl: string;
|
||||
let fakeTransport: ITransport = {
|
||||
connect(url: string): Promise<void> {
|
||||
|
|
@ -156,10 +145,23 @@ describe("Connection", () => {
|
|||
onClosed: undefined
|
||||
}
|
||||
|
||||
var connection = new Connection("http://tempuri.org?q=myData", options);
|
||||
let options: IHttpConnectionOptions = {
|
||||
httpClient: <IHttpClient>{
|
||||
options(url: string): Promise<string> {
|
||||
return Promise.resolve("{ \"connectionId\": \"42\" }");
|
||||
},
|
||||
get(url: string): Promise<string> {
|
||||
return Promise.resolve("");
|
||||
}
|
||||
},
|
||||
transport: fakeTransport
|
||||
} as IHttpConnectionOptions;
|
||||
|
||||
|
||||
var connection = new HttpConnection("http://tempuri.org?q=myData", options);
|
||||
|
||||
try {
|
||||
await connection.start(fakeTransport);
|
||||
await connection.start();
|
||||
fail();
|
||||
done();
|
||||
}
|
||||
|
|
@ -172,7 +174,7 @@ describe("Connection", () => {
|
|||
|
||||
eachTransport((requestedTransport: TransportType) => {
|
||||
it(`Connection cannot be started if requested ${TransportType[requestedTransport]} transport not available on server`, async done => {
|
||||
let options: ISignalROptions = {
|
||||
let options: IHttpConnectionOptions = {
|
||||
httpClient: <IHttpClient>{
|
||||
options(url: string): Promise<string> {
|
||||
return Promise.resolve("{ \"connectionId\": \"42\", \"availableTransports\": [] }");
|
||||
|
|
@ -180,12 +182,13 @@ describe("Connection", () => {
|
|||
get(url: string): Promise<string> {
|
||||
return Promise.resolve("");
|
||||
}
|
||||
}
|
||||
} as ISignalROptions;
|
||||
},
|
||||
transport: requestedTransport
|
||||
} as IHttpConnectionOptions;
|
||||
|
||||
var connection = new Connection("http://tempuri.org", options);
|
||||
var connection = new HttpConnection("http://tempuri.org", options);
|
||||
try {
|
||||
await connection.start(requestedTransport);
|
||||
await connection.start();
|
||||
fail();
|
||||
done();
|
||||
}
|
||||
|
|
@ -197,7 +200,7 @@ describe("Connection", () => {
|
|||
});
|
||||
|
||||
it(`Connection cannot be started if no transport available on server and no transport requested`, async done => {
|
||||
let options: ISignalROptions = {
|
||||
let options: IHttpConnectionOptions = {
|
||||
httpClient: <IHttpClient>{
|
||||
options(url: string): Promise<string> {
|
||||
return Promise.resolve("{ \"connectionId\": \"42\", \"availableTransports\": [] }");
|
||||
|
|
@ -206,9 +209,9 @@ describe("Connection", () => {
|
|||
return Promise.resolve("");
|
||||
}
|
||||
}
|
||||
} as ISignalROptions;
|
||||
} as IHttpConnectionOptions;
|
||||
|
||||
var connection = new Connection("http://tempuri.org", options);
|
||||
var connection = new HttpConnection("http://tempuri.org", options);
|
||||
try {
|
||||
await connection.start();
|
||||
fail();
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ describe("HubConnection", () => {
|
|||
});
|
||||
|
||||
class TestConnection implements IConnection {
|
||||
start(transportType: TransportType | ITransport): Promise<void> {
|
||||
start(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { DataReceived, ConnectionClosed } from "./Common"
|
|||
import { IConnection } from "./IConnection"
|
||||
import { ITransport, TransportType, WebSocketTransport, ServerSentEventsTransport, LongPollingTransport } from "./Transports"
|
||||
import { IHttpClient, HttpClient } from "./HttpClient"
|
||||
import { ISignalROptions } from "./ISignalROptions"
|
||||
import { IHttpConnectionOptions } from "./IHttpConnectionOptions"
|
||||
|
||||
enum ConnectionState {
|
||||
Initial,
|
||||
|
|
@ -16,32 +16,34 @@ interface INegotiateResponse {
|
|||
availableTransports: string[]
|
||||
}
|
||||
|
||||
export class Connection implements IConnection {
|
||||
export class HttpConnection implements IConnection {
|
||||
private connectionState: ConnectionState;
|
||||
private url: string;
|
||||
private connectionId: string;
|
||||
private httpClient: IHttpClient;
|
||||
private transport: ITransport;
|
||||
private options: IHttpConnectionOptions;
|
||||
private startPromise: Promise<void>;
|
||||
|
||||
constructor(url: string, options: ISignalROptions = {}) {
|
||||
constructor(url: string, options: IHttpConnectionOptions = {}) {
|
||||
this.url = url;
|
||||
this.httpClient = options.httpClient || new HttpClient();
|
||||
this.connectionState = ConnectionState.Initial;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
async start(transport?: TransportType | ITransport): Promise<void> {
|
||||
async start(): Promise<void> {
|
||||
if (this.connectionState != ConnectionState.Initial) {
|
||||
return Promise.reject(new Error("Cannot start a connection that is not in the 'Initial' state."));
|
||||
}
|
||||
|
||||
this.connectionState = ConnectionState.Connecting;
|
||||
|
||||
this.startPromise = this.startInternal(transport);
|
||||
this.startPromise = this.startInternal();
|
||||
return this.startPromise;
|
||||
}
|
||||
|
||||
private async startInternal(transportType: TransportType | ITransport): Promise<void> {
|
||||
private async startInternal(): Promise<void> {
|
||||
try {
|
||||
let negotiatePayload = await this.httpClient.options(this.url);
|
||||
let negotiateResponse: INegotiateResponse = JSON.parse(negotiatePayload);
|
||||
|
|
@ -54,7 +56,7 @@ export class Connection implements IConnection {
|
|||
|
||||
this.url += (this.url.indexOf("?") == -1 ? "?" : "&") + `id=${this.connectionId}`;
|
||||
|
||||
this.transport = this.createTransport(transportType, negotiateResponse.availableTransports);
|
||||
this.transport = this.createTransport(this.options.transport, negotiateResponse.availableTransports);
|
||||
this.transport.onDataReceived = this.onDataReceived;
|
||||
this.transport.onClosed = e => this.stopConnection(true, e);
|
||||
await this.transport.connect(this.url);
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
import { ConnectionClosed } from "./Common"
|
||||
import { IConnection } from "./IConnection"
|
||||
import { Connection } from "./Connection"
|
||||
import { TransportType } from "./Transports"
|
||||
import { Subject, Observable } from "./Observable"
|
||||
export { Connection } from "./Connection"
|
||||
export { TransportType } from "./Transports"
|
||||
export { HttpConnection } from "./HttpConnection"
|
||||
import { IHubProtocol, MessageType, HubMessage, CompletionMessage, ResultMessage, InvocationMessage } from "./IHubProtocol";
|
||||
import { JsonHubProtocol } from "./JsonHubProtocol";
|
||||
|
||||
|
|
@ -16,14 +15,8 @@ export class HubConnection {
|
|||
private connectionClosedCallback: ConnectionClosed;
|
||||
private protocol: IHubProtocol;
|
||||
|
||||
static create(url: string, queryString?: string): HubConnection {
|
||||
return new this(new Connection(url, queryString))
|
||||
}
|
||||
|
||||
constructor(connection: IConnection);
|
||||
constructor(url: string, queryString?: string);
|
||||
constructor(connectionOrUrl: IConnection | string, queryString?: string) {
|
||||
this.connection = typeof connectionOrUrl === "string" ? new Connection(connectionOrUrl, queryString) : connectionOrUrl;
|
||||
constructor(connection: IConnection) {
|
||||
this.connection = connection;
|
||||
this.connection.onDataReceived = data => {
|
||||
this.onDataReceived(data);
|
||||
};
|
||||
|
|
@ -96,8 +89,8 @@ export class HubConnection {
|
|||
}
|
||||
}
|
||||
|
||||
start(transportType?: TransportType): Promise<void> {
|
||||
return this.connection.start(transportType);
|
||||
start(): Promise<void> {
|
||||
return this.connection.start();
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { DataReceived, ConnectionClosed } from "./Common"
|
|||
import { TransportType, ITransport } from "./Transports"
|
||||
|
||||
export interface IConnection {
|
||||
start(transportType: TransportType | ITransport): Promise<void>;
|
||||
start(): Promise<void>;
|
||||
send(data: any): Promise<void>;
|
||||
stop(): void;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
import { IHttpClient } from "./HttpClient"
|
||||
import { TransportType, ITransport } from "./Transports"
|
||||
|
||||
export interface IHttpConnectionOptions {
|
||||
httpClient?: IHttpClient;
|
||||
transport?: TransportType | ITransport;
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
import {IHttpClient} from "./HttpClient"
|
||||
|
||||
export interface ISignalROptions {
|
||||
httpClient?: IHttpClient;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
export * from "./Common"
|
||||
export * from "./Connection"
|
||||
export * from "./HttpConnection"
|
||||
export * from "./HttpClient"
|
||||
export * from "./HubConnection"
|
||||
export * from "./Transports"
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@
|
|||
<script src="lib/signalr-client/signalr-client.js"></script>
|
||||
<script>
|
||||
let transportType = signalR.TransportType[getParameterByName('transport')] || signalR.TransportType.WebSockets;
|
||||
let connection = new signalR.HubConnection(`http://${document.location.host}/chat`, 'formatType=json&format=text');
|
||||
let http = new signalR.HttpConnection(`http://${document.location.host}/chat`, { transport: transportType });
|
||||
let connection = new signalR.HubConnection(http);
|
||||
|
||||
connection.onClosed = e => {
|
||||
if (e) {
|
||||
|
|
@ -59,7 +60,7 @@ connection.on('Send', (userName, message) => {
|
|||
document.getElementById('messages').appendChild(child);
|
||||
});
|
||||
|
||||
connection.start(transportType).catch(err => appendLine(err, 'red'));
|
||||
connection.start().catch(err => appendLine(err, 'red'));
|
||||
|
||||
document.getElementById('sendmessage').addEventListener('submit', event => {
|
||||
let data = document.getElementById('new-message').value;
|
||||
|
|
|
|||
|
|
@ -81,7 +81,8 @@ let transportType = signalR.TransportType[getParameterByName('transport')] || si
|
|||
|
||||
document.getElementById('head1').innerHTML = signalR.TransportType[transportType];
|
||||
|
||||
let connection = new signalR.HubConnection(`http://${document.location.host}/hubs`, 'formatType=json&format=text');
|
||||
let http = new signalR.HttpConnection(`http://${document.location.host}/hubs`, { transport: transportType });
|
||||
let connection = new signalR.HubConnection(http);
|
||||
connection.on('Send', msg => {
|
||||
addLine('message-list', msg);
|
||||
});
|
||||
|
|
@ -96,7 +97,7 @@ connection.onClosed = e => {
|
|||
}
|
||||
|
||||
click('connect', event => {
|
||||
connection.start(transportType)
|
||||
connection.start()
|
||||
.then(() => {
|
||||
isConnected = true;
|
||||
addLine('message-list', 'Connected successfully', 'green');
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
document.getElementById('transportName').innerHTML = signalR.TransportType[transportType];
|
||||
|
||||
let url = `http://${document.location.host}/chat`
|
||||
let connection = new signalR.Connection(url);
|
||||
let connection = new signalR.HttpConnection(url, { transport: transportType });
|
||||
|
||||
connection.onDataReceived = data => {
|
||||
let child = document.createElement('li');
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
event.preventDefault();
|
||||
});
|
||||
|
||||
connection.start(transportType).then(() => {
|
||||
connection.start().then(() => {
|
||||
console.log("Opened");
|
||||
}, () => {
|
||||
console.log("Error opening connection");
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
|
@ -53,7 +53,8 @@
|
|||
});
|
||||
|
||||
click('connectButton', function () {
|
||||
connection = new signalR.HubConnection(url, 'formatType=json&format=text');
|
||||
let http = new signalR.HttpConnection(url, { transport: transportType });
|
||||
connection = new signalR.HubConnection(http);
|
||||
|
||||
connection.onClosed = function () {
|
||||
channelButton.disabled = true;
|
||||
|
|
@ -64,7 +65,7 @@
|
|||
addLine('resultsList', 'disconnected', 'green');
|
||||
};
|
||||
|
||||
connection.start(transportType)
|
||||
connection.start()
|
||||
.then(function () {
|
||||
channelButton.disabled = false;
|
||||
observableButton.disabled = false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue