Merge branch 'rel/1.0.0-alpha1' into dev

This commit is contained in:
Pawel Kadluczka 2017-09-11 21:31:02 -07:00
commit 0557319870
10 changed files with 108 additions and 62 deletions

View File

@ -9,6 +9,10 @@ import { ITransport, TransportType, TransferMode } from "../Microsoft.AspNetCore
import { eachTransport } from "./Common";
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) => {
let options: IHttpConnectionOptions = {

View File

@ -22,7 +22,8 @@ export namespace TextMessageFormat {
export namespace BinaryMessageFormat {
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);
// javascript bitwise operators only support 32-bit integers

View File

@ -34,10 +34,10 @@ export class HttpConnection implements IConnection {
readonly features: any = {};
constructor(url: string, options: IHttpConnectionOptions = {}) {
this.url = url;
this.logger = LoggerFactory.createLogger(options.logging);
this.url = this.resolveUrl(url);
options = options || {};
this.httpClient = options.httpClient || new HttpClient();
this.logger = LoggerFactory.createLogger(options.logging);
this.connectionState = ConnectionState.Initial;
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;
onClosed: ConnectionClosed;
}

View File

@ -3,6 +3,7 @@
import { ConnectionClosed } from "./Common"
import { IConnection } from "./IConnection"
import { HttpConnection} from "./HttpConnection"
import { TransportType, TransferMode } from "./Transports"
import { Subject, Observable } from "./Observable"
import { IHubProtocol, ProtocolType, MessageType, HubMessage, CompletionMessage, ResultMessage, InvocationMessage, NegotiationMessage } from "./IHubProtocol";
@ -28,9 +29,15 @@ export class HubConnection {
private id: number;
private connectionClosedCallback: ConnectionClosed;
constructor(connection: IConnection, options: IHubConnectionOptions = {}) {
this.connection = connection;
constructor(urlOrConnection: string | IConnection, options: IHubConnectionOptions = {}) {
options = options || {};
if (typeof urlOrConnection === "string") {
this.connection = new HttpConnection(urlOrConnection, options);
}
else {
this.connection = urlOrConnection;
}
this.logger = LoggerFactory.createLogger(options.logging);
this.protocol = options.protocol || new JsonHubProtocol();

View File

@ -1,10 +1,10 @@
// 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 { IHttpConnectionOptions } from "./IHttpConnectionOptions"
import { IHubProtocol } from "./IHubProtocol"
import { ILogger, LogLevel } from "./ILogger"
export interface IHubConnectionOptions {
export interface IHubConnectionOptions extends IHttpConnectionOptions {
protocol?: IHubProtocol;
logging?: ILogger | LogLevel;
}

View File

@ -247,12 +247,12 @@ export class LongPollingTransport implements ITransport {
}
this.pollXhr = pollXhr;
this.pollXhr.open("GET", url, true);
this.pollXhr.open("GET", `${url}&_=${Date.now()}`, true);
if (transferMode === TransferMode.Binary) {
this.pollXhr.responseType = "arraybuffer";
}
// IE caches xhr requests
this.pollXhr.setRequestHeader("Cache-Control", "no-cache");
// TODO: consider making timeout configurable
this.pollXhr.timeout = 120000;
this.pollXhr.send();

View File

@ -6,7 +6,10 @@
var ECHOENDPOINT_URL = "http://" + document.location.host + "/echo";
function getTransportTypes() {
var transportTypes = [signalR.TransportType.WebSockets];
var transportTypes = [];
if (typeof WebSocket !== "undefined") {
transportTypes.push(signalR.TransportType.WebSockets);
}
if (typeof EventSource !== "undefined") {
transportTypes.push(signalR.TransportType.ServerSentEvents);
}
@ -22,7 +25,12 @@ function eachTransport(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) {
return protocols.forEach(function (p) {
return action(t, p);

View File

@ -4,30 +4,32 @@
"use strict";
describe('connection', function () {
it("can connect to the server without specifying transport explicitly", function (done) {
var message = "Hello World!";
var connection = new signalR.HttpConnection(ECHOENDPOINT_URL);
if (typeof WebSocket !== 'undefined') {
it("can connect to the server without specifying transport explicitly", function (done) {
var message = "Hello World!";
var connection = new signalR.HttpConnection(ECHOENDPOINT_URL);
var received = "";
connection.onDataReceived = function (data) {
received += data;
if (data == message) {
connection.stop();
}
};
var received = "";
connection.onDataReceived = function (data) {
received += data;
if (data == message) {
connection.stop();
}
};
connection.onClosed = function (error) {
expect(error).toBeUndefined();
done();
};
connection.onClosed = function (error) {
expect(error).toBeUndefined();
done();
};
connection.start().then(function () {
connection.send(message);
}).catch(function (e) {
fail();
done();
connection.start().then(function () {
connection.send(message);
}).catch(function (e) {
fail();
done();
});
});
});
}
eachTransport(function (transportType) {
it("over " + signalR.TransportType[transportType] + " can send and receive messages", function (done) {

View File

@ -3,7 +3,7 @@
'use strict';
var TESTHUBENDPOINT_URL = 'http://' + document.location.host + '/testhub';
var TESTHUBENDPOINT_URL = '/testhub';
describe('hubConnection', function () {
eachTransportAndProtocol(function (transportType, protocol) {
@ -17,7 +17,7 @@ describe('hubConnection', function () {
protocol: protocol,
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) {
expect(error).toBe(undefined);
done();
@ -44,7 +44,7 @@ describe('hubConnection', function () {
protocol: protocol,
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) {
expect(error).toBe(undefined);
@ -79,7 +79,7 @@ describe('hubConnection', function () {
protocol: protocol,
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.invoke('ThrowException', errorMessage).then(function () {
@ -105,7 +105,7 @@ describe('hubConnection', function () {
protocol: protocol,
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.stream('ThrowException', errorMessage).subscribe({
@ -132,7 +132,7 @@ describe('hubConnection', function () {
protocol: protocol,
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";
@ -170,7 +170,7 @@ describe('hubConnection', function () {
protocol: protocol,
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) {
expect(error.message).toMatch(errorRegex[signalR.TransportType[transportType]]);

View File

@ -3,33 +3,35 @@
'use strict';
describe('WebSockets', function () {
it('can be used to connect to SignalR', function (done) {
var message = "message";
if (typeof WebSocket !== 'undefined') {
describe('WebSockets', function () {
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.send(message);
};
webSocket.onopen = function () {
webSocket.send(message);
};
var received = "";
webSocket.onmessage = function (event) {
received += event.data;
if (received === message) {
webSocket.close();
}
};
var received = "";
webSocket.onmessage = function (event) {
received += event.data;
if (received === message) {
webSocket.close();
}
};
webSocket.onclose = function (event) {
if (!event.wasClean) {
fail("connection closed with unexpected status code: " + event.code + " " + event.reason);
}
webSocket.onclose = function (event) {
if (!event.wasClean) {
fail("connection closed with unexpected status code: " + event.code + " " + event.reason);
}
// Jasmine doesn't like tests without expectations
expect(event.wasClean).toBe(true);
// Jasmine doesn't like tests without expectations
expect(event.wasClean).toBe(true);
done();
};
done();
};
});
});
});
}