Merge branch 'rel/1.0.0-alpha1' into dev
This commit is contained in:
commit
0557319870
|
|
@ -9,6 +9,10 @@ import { ITransport, TransportType, TransferMode } from "../Microsoft.AspNetCore
|
||||||
import { eachTransport } from "./Common";
|
import { eachTransport } from "./Common";
|
||||||
|
|
||||||
describe("Connection", () => {
|
describe("Connection", () => {
|
||||||
|
it("cannot be created with relative url if document object is not present", () => {
|
||||||
|
expect(() => new HttpConnection("/test"))
|
||||||
|
.toThrow(new Error("Cannot resolve '/test'."));
|
||||||
|
});
|
||||||
|
|
||||||
it("starting connection fails if getting id fails", async (done) => {
|
it("starting connection fails if getting id fails", async (done) => {
|
||||||
let options: IHttpConnectionOptions = {
|
let options: IHttpConnectionOptions = {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@ export namespace TextMessageFormat {
|
||||||
|
|
||||||
export namespace BinaryMessageFormat {
|
export namespace BinaryMessageFormat {
|
||||||
export function write(output: Uint8Array): ArrayBuffer {
|
export function write(output: Uint8Array): ArrayBuffer {
|
||||||
let size = output.byteLength;
|
// .byteLength does is undefined in IE10
|
||||||
|
let size = output.byteLength || output.length;
|
||||||
let buffer = new Uint8Array(size + 8);
|
let buffer = new Uint8Array(size + 8);
|
||||||
|
|
||||||
// javascript bitwise operators only support 32-bit integers
|
// javascript bitwise operators only support 32-bit integers
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,10 @@ export class HttpConnection implements IConnection {
|
||||||
readonly features: any = {};
|
readonly features: any = {};
|
||||||
|
|
||||||
constructor(url: string, options: IHttpConnectionOptions = {}) {
|
constructor(url: string, options: IHttpConnectionOptions = {}) {
|
||||||
this.url = url;
|
this.logger = LoggerFactory.createLogger(options.logging);
|
||||||
|
this.url = this.resolveUrl(url);
|
||||||
options = options || {};
|
options = options || {};
|
||||||
this.httpClient = options.httpClient || new HttpClient();
|
this.httpClient = options.httpClient || new HttpClient();
|
||||||
this.logger = LoggerFactory.createLogger(options.logging);
|
|
||||||
this.connectionState = ConnectionState.Initial;
|
this.connectionState = ConnectionState.Initial;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
@ -156,6 +156,28 @@ export class HttpConnection implements IConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private resolveUrl(url: string) : string {
|
||||||
|
// startsWith is not supported in IE
|
||||||
|
if (url.lastIndexOf("https://", 0) === 0 || url.lastIndexOf("http://", 0) === 0) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
throw new Error(`Cannot resolve '${url}'.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let parser = window.document.createElement("a");
|
||||||
|
parser.href = url;
|
||||||
|
|
||||||
|
let baseUrl = (!parser.protocol || parser.protocol === ":")
|
||||||
|
? `${window.document.location.protocol}//${(parser.host || window.document.location.host)}`
|
||||||
|
: `${parser.protocol}//${parser.host}`;
|
||||||
|
|
||||||
|
let normalizedUrl = baseUrl + url;
|
||||||
|
this.logger.log(LogLevel.Information, `Normalizing '${url}' to '${normalizedUrl}'`);
|
||||||
|
return normalizedUrl;
|
||||||
|
}
|
||||||
|
|
||||||
onDataReceived: DataReceived;
|
onDataReceived: DataReceived;
|
||||||
onClosed: ConnectionClosed;
|
onClosed: ConnectionClosed;
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import { ConnectionClosed } from "./Common"
|
import { ConnectionClosed } from "./Common"
|
||||||
import { IConnection } from "./IConnection"
|
import { IConnection } from "./IConnection"
|
||||||
|
import { HttpConnection} from "./HttpConnection"
|
||||||
import { TransportType, TransferMode } from "./Transports"
|
import { TransportType, TransferMode } from "./Transports"
|
||||||
import { Subject, Observable } from "./Observable"
|
import { Subject, Observable } from "./Observable"
|
||||||
import { IHubProtocol, ProtocolType, MessageType, HubMessage, CompletionMessage, ResultMessage, InvocationMessage, NegotiationMessage } from "./IHubProtocol";
|
import { IHubProtocol, ProtocolType, MessageType, HubMessage, CompletionMessage, ResultMessage, InvocationMessage, NegotiationMessage } from "./IHubProtocol";
|
||||||
|
|
@ -28,9 +29,15 @@ export class HubConnection {
|
||||||
private id: number;
|
private id: number;
|
||||||
private connectionClosedCallback: ConnectionClosed;
|
private connectionClosedCallback: ConnectionClosed;
|
||||||
|
|
||||||
constructor(connection: IConnection, options: IHubConnectionOptions = {}) {
|
constructor(urlOrConnection: string | IConnection, options: IHubConnectionOptions = {}) {
|
||||||
this.connection = connection;
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
if (typeof urlOrConnection === "string") {
|
||||||
|
this.connection = new HttpConnection(urlOrConnection, options);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.connection = urlOrConnection;
|
||||||
|
}
|
||||||
|
|
||||||
this.logger = LoggerFactory.createLogger(options.logging);
|
this.logger = LoggerFactory.createLogger(options.logging);
|
||||||
|
|
||||||
this.protocol = options.protocol || new JsonHubProtocol();
|
this.protocol = options.protocol || new JsonHubProtocol();
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
import { IHttpConnectionOptions } from "./IHttpConnectionOptions"
|
||||||
import { IHubProtocol } from "./IHubProtocol"
|
import { IHubProtocol } from "./IHubProtocol"
|
||||||
import { ILogger, LogLevel } from "./ILogger"
|
import { ILogger, LogLevel } from "./ILogger"
|
||||||
|
|
||||||
export interface IHubConnectionOptions {
|
export interface IHubConnectionOptions extends IHttpConnectionOptions {
|
||||||
protocol?: IHubProtocol;
|
protocol?: IHubProtocol;
|
||||||
logging?: ILogger | LogLevel;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -247,12 +247,12 @@ export class LongPollingTransport implements ITransport {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pollXhr = pollXhr;
|
this.pollXhr = pollXhr;
|
||||||
this.pollXhr.open("GET", url, true);
|
|
||||||
|
this.pollXhr.open("GET", `${url}&_=${Date.now()}`, true);
|
||||||
if (transferMode === TransferMode.Binary) {
|
if (transferMode === TransferMode.Binary) {
|
||||||
this.pollXhr.responseType = "arraybuffer";
|
this.pollXhr.responseType = "arraybuffer";
|
||||||
}
|
}
|
||||||
// IE caches xhr requests
|
|
||||||
this.pollXhr.setRequestHeader("Cache-Control", "no-cache");
|
|
||||||
// TODO: consider making timeout configurable
|
// TODO: consider making timeout configurable
|
||||||
this.pollXhr.timeout = 120000;
|
this.pollXhr.timeout = 120000;
|
||||||
this.pollXhr.send();
|
this.pollXhr.send();
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,10 @@
|
||||||
var ECHOENDPOINT_URL = "http://" + document.location.host + "/echo";
|
var ECHOENDPOINT_URL = "http://" + document.location.host + "/echo";
|
||||||
|
|
||||||
function getTransportTypes() {
|
function getTransportTypes() {
|
||||||
var transportTypes = [signalR.TransportType.WebSockets];
|
var transportTypes = [];
|
||||||
|
if (typeof WebSocket !== "undefined") {
|
||||||
|
transportTypes.push(signalR.TransportType.WebSockets);
|
||||||
|
}
|
||||||
if (typeof EventSource !== "undefined") {
|
if (typeof EventSource !== "undefined") {
|
||||||
transportTypes.push(signalR.TransportType.ServerSentEvents);
|
transportTypes.push(signalR.TransportType.ServerSentEvents);
|
||||||
}
|
}
|
||||||
|
|
@ -22,7 +25,12 @@ function eachTransport(action) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function eachTransportAndProtocol(action) {
|
function eachTransportAndProtocol(action) {
|
||||||
var protocols = [new signalR.JsonHubProtocol(), new signalRMsgPack.MessagePackHubProtocol()];
|
var protocols = [new signalR.JsonHubProtocol()];
|
||||||
|
// IE9 does not support XmlHttpRequest advanced features so disable for now
|
||||||
|
// This can be enabled if we fix: https://github.com/aspnet/SignalR/issues/742
|
||||||
|
if (typeof new XMLHttpRequest().responseType === "string") {
|
||||||
|
protocols.push(new signalRMsgPack.MessagePackHubProtocol());
|
||||||
|
}
|
||||||
getTransportTypes().forEach(function (t) {
|
getTransportTypes().forEach(function (t) {
|
||||||
return protocols.forEach(function (p) {
|
return protocols.forEach(function (p) {
|
||||||
return action(t, p);
|
return action(t, p);
|
||||||
|
|
|
||||||
|
|
@ -4,30 +4,32 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
describe('connection', function () {
|
describe('connection', function () {
|
||||||
it("can connect to the server without specifying transport explicitly", function (done) {
|
if (typeof WebSocket !== 'undefined') {
|
||||||
var message = "Hello World!";
|
it("can connect to the server without specifying transport explicitly", function (done) {
|
||||||
var connection = new signalR.HttpConnection(ECHOENDPOINT_URL);
|
var message = "Hello World!";
|
||||||
|
var connection = new signalR.HttpConnection(ECHOENDPOINT_URL);
|
||||||
|
|
||||||
var received = "";
|
var received = "";
|
||||||
connection.onDataReceived = function (data) {
|
connection.onDataReceived = function (data) {
|
||||||
received += data;
|
received += data;
|
||||||
if (data == message) {
|
if (data == message) {
|
||||||
connection.stop();
|
connection.stop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
connection.onClosed = function (error) {
|
connection.onClosed = function (error) {
|
||||||
expect(error).toBeUndefined();
|
expect(error).toBeUndefined();
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
|
|
||||||
connection.start().then(function () {
|
connection.start().then(function () {
|
||||||
connection.send(message);
|
connection.send(message);
|
||||||
}).catch(function (e) {
|
}).catch(function (e) {
|
||||||
fail();
|
fail();
|
||||||
done();
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
eachTransport(function (transportType) {
|
eachTransport(function (transportType) {
|
||||||
it("over " + signalR.TransportType[transportType] + " can send and receive messages", function (done) {
|
it("over " + signalR.TransportType[transportType] + " can send and receive messages", function (done) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var TESTHUBENDPOINT_URL = 'http://' + document.location.host + '/testhub';
|
var TESTHUBENDPOINT_URL = '/testhub';
|
||||||
|
|
||||||
describe('hubConnection', function () {
|
describe('hubConnection', function () {
|
||||||
eachTransportAndProtocol(function (transportType, protocol) {
|
eachTransportAndProtocol(function (transportType, protocol) {
|
||||||
|
|
@ -17,7 +17,7 @@ describe('hubConnection', function () {
|
||||||
protocol: protocol,
|
protocol: protocol,
|
||||||
logging: signalR.LogLevel.Trace
|
logging: signalR.LogLevel.Trace
|
||||||
};
|
};
|
||||||
var hubConnection = new signalR.HubConnection(new signalR.HttpConnection(TESTHUBENDPOINT_URL, options), options);
|
var hubConnection = new signalR.HubConnection(TESTHUBENDPOINT_URL, options);
|
||||||
hubConnection.onClosed = function (error) {
|
hubConnection.onClosed = function (error) {
|
||||||
expect(error).toBe(undefined);
|
expect(error).toBe(undefined);
|
||||||
done();
|
done();
|
||||||
|
|
@ -44,7 +44,7 @@ describe('hubConnection', function () {
|
||||||
protocol: protocol,
|
protocol: protocol,
|
||||||
logging: signalR.LogLevel.Trace
|
logging: signalR.LogLevel.Trace
|
||||||
};
|
};
|
||||||
var hubConnection = new signalR.HubConnection(new signalR.HttpConnection(TESTHUBENDPOINT_URL, options), options);
|
var hubConnection = new signalR.HubConnection(TESTHUBENDPOINT_URL, options);
|
||||||
|
|
||||||
hubConnection.onClosed = function (error) {
|
hubConnection.onClosed = function (error) {
|
||||||
expect(error).toBe(undefined);
|
expect(error).toBe(undefined);
|
||||||
|
|
@ -79,7 +79,7 @@ describe('hubConnection', function () {
|
||||||
protocol: protocol,
|
protocol: protocol,
|
||||||
logging: signalR.LogLevel.Trace
|
logging: signalR.LogLevel.Trace
|
||||||
};
|
};
|
||||||
var hubConnection = new signalR.HubConnection(new signalR.HttpConnection(TESTHUBENDPOINT_URL, options), options);
|
var hubConnection = new signalR.HubConnection(TESTHUBENDPOINT_URL, options);
|
||||||
|
|
||||||
hubConnection.start().then(function () {
|
hubConnection.start().then(function () {
|
||||||
hubConnection.invoke('ThrowException', errorMessage).then(function () {
|
hubConnection.invoke('ThrowException', errorMessage).then(function () {
|
||||||
|
|
@ -105,7 +105,7 @@ describe('hubConnection', function () {
|
||||||
protocol: protocol,
|
protocol: protocol,
|
||||||
logging: signalR.LogLevel.Trace
|
logging: signalR.LogLevel.Trace
|
||||||
};
|
};
|
||||||
var hubConnection = new signalR.HubConnection(new signalR.HttpConnection(TESTHUBENDPOINT_URL, options), options);
|
var hubConnection = new signalR.HubConnection(TESTHUBENDPOINT_URL, options);
|
||||||
|
|
||||||
hubConnection.start().then(function () {
|
hubConnection.start().then(function () {
|
||||||
hubConnection.stream('ThrowException', errorMessage).subscribe({
|
hubConnection.stream('ThrowException', errorMessage).subscribe({
|
||||||
|
|
@ -132,7 +132,7 @@ describe('hubConnection', function () {
|
||||||
protocol: protocol,
|
protocol: protocol,
|
||||||
logging: signalR.LogLevel.Trace
|
logging: signalR.LogLevel.Trace
|
||||||
};
|
};
|
||||||
var hubConnection = new signalR.HubConnection(new signalR.HttpConnection(TESTHUBENDPOINT_URL, options), options);
|
var hubConnection = new signalR.HubConnection(TESTHUBENDPOINT_URL, options);
|
||||||
|
|
||||||
var message = "你好 SignalR!";
|
var message = "你好 SignalR!";
|
||||||
|
|
||||||
|
|
@ -170,7 +170,7 @@ describe('hubConnection', function () {
|
||||||
protocol: protocol,
|
protocol: protocol,
|
||||||
logging: signalR.LogLevel.Trace
|
logging: signalR.LogLevel.Trace
|
||||||
};
|
};
|
||||||
var hubConnection = new signalR.HubConnection(new signalR.HttpConnection('http://' + document.location.host + '/uncreatable', options), options);
|
var hubConnection = new signalR.HubConnection('http://' + document.location.host + '/uncreatable', options);
|
||||||
|
|
||||||
hubConnection.onClosed = function (error) {
|
hubConnection.onClosed = function (error) {
|
||||||
expect(error.message).toMatch(errorRegex[signalR.TransportType[transportType]]);
|
expect(error.message).toMatch(errorRegex[signalR.TransportType[transportType]]);
|
||||||
|
|
|
||||||
|
|
@ -3,33 +3,35 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
describe('WebSockets', function () {
|
if (typeof WebSocket !== 'undefined') {
|
||||||
it('can be used to connect to SignalR', function (done) {
|
describe('WebSockets', function () {
|
||||||
var message = "message";
|
it('can be used to connect to SignalR', function (done) {
|
||||||
|
var message = "message";
|
||||||
|
|
||||||
var webSocket = new WebSocket(ECHOENDPOINT_URL.replace(/^http/, "ws"));
|
var webSocket = new WebSocket(ECHOENDPOINT_URL.replace(/^http/, "ws"));
|
||||||
|
|
||||||
webSocket.onopen = function () {
|
webSocket.onopen = function () {
|
||||||
webSocket.send(message);
|
webSocket.send(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
var received = "";
|
var received = "";
|
||||||
webSocket.onmessage = function (event) {
|
webSocket.onmessage = function (event) {
|
||||||
received += event.data;
|
received += event.data;
|
||||||
if (received === message) {
|
if (received === message) {
|
||||||
webSocket.close();
|
webSocket.close();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
webSocket.onclose = function (event) {
|
webSocket.onclose = function (event) {
|
||||||
if (!event.wasClean) {
|
if (!event.wasClean) {
|
||||||
fail("connection closed with unexpected status code: " + event.code + " " + event.reason);
|
fail("connection closed with unexpected status code: " + event.code + " " + event.reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jasmine doesn't like tests without expectations
|
// Jasmine doesn't like tests without expectations
|
||||||
expect(event.wasClean).toBe(true);
|
expect(event.wasClean).toBe(true);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue