Merge branch 'release/2.2'
This commit is contained in:
commit
a260d44fe2
|
|
@ -8,9 +8,13 @@
|
|||
"version": "file:../signalr",
|
||||
"requires": {
|
||||
"eventsource": "^1.0.7",
|
||||
"websocket": "^1.0.26"
|
||||
"ws": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"async-limiter": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"bundled": true,
|
||||
|
|
@ -85,6 +89,13 @@
|
|||
"yaeti": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "6.0.0",
|
||||
"bundled": true,
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"yaeti": {
|
||||
"version": "0.0.6",
|
||||
"bundled": true
|
||||
|
|
@ -1086,6 +1097,19 @@
|
|||
"debug": "~3.1.0",
|
||||
"engine.io-parser": "~2.1.0",
|
||||
"ws": "~3.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
|
||||
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0",
|
||||
"safe-buffer": "~5.1.0",
|
||||
"ultron": "~1.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"engine.io-client": {
|
||||
|
|
@ -1105,6 +1129,19 @@
|
|||
"ws": "~3.3.1",
|
||||
"xmlhttprequest-ssl": "~1.5.4",
|
||||
"yeast": "0.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
|
||||
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0",
|
||||
"safe-buffer": "~5.1.0",
|
||||
"ultron": "~1.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"engine.io-parser": {
|
||||
|
|
@ -1523,14 +1560,12 @@
|
|||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
|
@ -1545,20 +1580,17 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
|
@ -1675,8 +1707,7 @@
|
|||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
|
@ -1688,7 +1719,6 @@
|
|||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
|
@ -1703,7 +1733,6 @@
|
|||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
|
@ -1711,14 +1740,12 @@
|
|||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.2.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.1",
|
||||
"yallist": "^3.0.0"
|
||||
|
|
@ -1737,7 +1764,6 @@
|
|||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
|
@ -1818,8 +1844,7 @@
|
|||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
|
@ -1831,7 +1856,6 @@
|
|||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
|
@ -1953,7 +1977,6 @@
|
|||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
|
@ -2799,7 +2822,8 @@
|
|||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
|
||||
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.13",
|
||||
|
|
@ -3710,15 +3734,6 @@
|
|||
"mime-types": "~2.1.18"
|
||||
}
|
||||
},
|
||||
"typedarray-to-buffer": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
||||
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.1.tgz",
|
||||
|
|
@ -4018,29 +4033,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"websocket": {
|
||||
"version": "1.0.26",
|
||||
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.26.tgz",
|
||||
"integrity": "sha512-fjcrYDPIQxpTnqFQ9JjxUQcdvR89MFAOjPBlF+vjOt49w/XW4fJknUoMz/mDIn2eK1AdslVojcaOxOqyZZV8rw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "^2.2.0",
|
||||
"nan": "^2.3.3",
|
||||
"typedarray-to-buffer": "^3.1.2",
|
||||
"yaeti": "^0.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||
|
|
@ -4063,14 +4055,12 @@
|
|||
"dev": true
|
||||
},
|
||||
"ws": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
|
||||
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.0.0.tgz",
|
||||
"integrity": "sha512-c2UlYcAZp1VS8AORtpq6y4RJIkJ9dQz18W32SpR/qXGfLDZ2jU4y4wKvvZwqbi7U6gxFQTeE+urMbXU/tsDy4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0",
|
||||
"safe-buffer": "~5.1.0",
|
||||
"ultron": "~1.1.0"
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"xmlbuilder": {
|
||||
|
|
@ -4091,12 +4081,6 @@
|
|||
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
|
||||
"dev": true
|
||||
},
|
||||
"yaeti": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
|
||||
"integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=",
|
||||
"dev": true
|
||||
},
|
||||
"yeast": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
"karma-summary-reporter": "^1.5.0",
|
||||
"ts-node": "^4.1.0",
|
||||
"typescript": "^3.0.1",
|
||||
"websocket": " ^1.0.26"
|
||||
"ws": " ^6.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "node ../common/node_modules/rimraf/bin.js ./wwwroot/dist ./obj/js",
|
||||
|
|
|
|||
|
|
@ -20,10 +20,9 @@ describe("WebSockets", () => {
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
const websocketModule = require("websocket");
|
||||
const hasWebsocket = websocketModule && websocketModule.w3cwebsocket;
|
||||
if (hasWebsocket) {
|
||||
webSocket = new websocketModule.w3cwebsocket(ECHOENDPOINT_URL.replace(/^http/, "ws"));
|
||||
const websocketModule = require("ws");
|
||||
if (websocketModule) {
|
||||
webSocket = new websocketModule(ECHOENDPOINT_URL.replace(/^http/, "ws"));
|
||||
} else {
|
||||
// No WebSockets implementations in current environment, skip test
|
||||
done();
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
"integrity": "sha512-EiFdEaD7EQNFl4PDBvlbPlX4hV8rJhEKfFj58jkjqvj1gN6E1lShu24cXeWH/RQ5nf+/ei4WGp70xp2ubBaE5Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
"@types/node": "8.5.5"
|
||||
}
|
||||
},
|
||||
"@types/msgpack5": {
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
"integrity": "sha512-E3wILUjTXONukpiI6tmqpLwf7eV3MVTdxpjz56FqNn7koMF/6sSPUh5TxMlwgoOhyeejxwVoNZUiDcdqChKkAw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/bl": "*"
|
||||
"@types/bl": "0.8.31"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
|
|
@ -39,8 +39,8 @@
|
|||
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
|
||||
"integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
|
||||
"requires": {
|
||||
"readable-stream": "^2.3.5",
|
||||
"safe-buffer": "^5.1.1"
|
||||
"readable-stream": "2.3.6",
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"buffer": {
|
||||
|
|
@ -49,8 +49,8 @@
|
|||
"integrity": "sha512-xXvjQhVNz50v2nPeoOsNqWCLGfiv4ji/gXZM28jnVwdLJxH4mFyqgqCKfaK9zf1KUbG6zTkjLOy7ou+jSMarGA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"base64-js": "^1.0.2",
|
||||
"ieee754": "^1.1.4"
|
||||
"base64-js": "1.2.1",
|
||||
"ieee754": "1.1.8"
|
||||
}
|
||||
},
|
||||
"core-util-is": {
|
||||
|
|
@ -79,10 +79,10 @@
|
|||
"resolved": "https://registry.npmjs.org/msgpack5/-/msgpack5-4.0.2.tgz",
|
||||
"integrity": "sha512-rEIx0/KFtWGtqlF5D/NIMzOHDhm7AhIFzHR3/PLqMrXXbMKoSitDE/IDuTactlTjxEc0ScmHx/5qoH015uL7xA==",
|
||||
"requires": {
|
||||
"bl": "^1.2.1",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^2.3.3",
|
||||
"safe-buffer": "^5.1.1"
|
||||
"bl": "1.2.2",
|
||||
"inherits": "2.0.3",
|
||||
"readable-stream": "2.3.6",
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"process-nextick-args": {
|
||||
|
|
@ -95,13 +95,13 @@
|
|||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
"core-util-is": "1.0.2",
|
||||
"inherits": "2.0.3",
|
||||
"isarray": "1.0.0",
|
||||
"process-nextick-args": "2.0.0",
|
||||
"safe-buffer": "5.1.1",
|
||||
"string_decoder": "1.1.1",
|
||||
"util-deprecate": "1.0.2"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
|
|
@ -114,7 +114,7 @@
|
|||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import * as msgpack5 from "msgpack5";
|
|||
import { CompletionMessage, HubMessage, IHubProtocol, ILogger, InvocationMessage, LogLevel, MessageHeaders, MessageType, NullLogger, StreamInvocationMessage, StreamItemMessage, TransferFormat } from "@aspnet/signalr";
|
||||
|
||||
import { BinaryMessageFormat } from "./BinaryMessageFormat";
|
||||
import { isArrayBuffer } from "./Utils";
|
||||
|
||||
// TypeDoc's @inheritDoc and @link don't work across modules :(
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ export class MessagePackHubProtocol implements IHubProtocol {
|
|||
*/
|
||||
public parseMessages(input: ArrayBuffer | Buffer, logger: ILogger): HubMessage[] {
|
||||
// The interface does allow "string" to be passed in, but this implementation does not. So let's throw a useful error.
|
||||
if (!(input instanceof ArrayBuffer) && !(input instanceof Buffer)) {
|
||||
if (!(input instanceof Buffer) && !(isArrayBuffer(input))) {
|
||||
throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer or Buffer.");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
// 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.
|
||||
|
||||
// Copied from signalr/Utils.ts
|
||||
/** @private */
|
||||
export function isArrayBuffer(val: any): val is ArrayBuffer {
|
||||
return val && typeof ArrayBuffer !== "undefined" &&
|
||||
(val instanceof ArrayBuffer ||
|
||||
// Sometimes we get an ArrayBuffer that doesn't satisfy instanceof
|
||||
(val.constructor && val.constructor.name === "ArrayBuffer"));
|
||||
}
|
||||
|
|
@ -4,12 +4,6 @@
|
|||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/events": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
|
||||
"integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/eventsource": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/eventsource/-/eventsource-1.0.2.tgz",
|
||||
|
|
@ -22,23 +16,10 @@
|
|||
"integrity": "sha512-fCHV45gS+m3hH17zgkgADUSi2RR1Vht6wOZ0jyHP8rjiQra9f+mIcgwPQHllmDocYOstIEbKlxbFDYlgrTPYqw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/websocket": {
|
||||
"version": "0.0.40",
|
||||
"resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-0.0.40.tgz",
|
||||
"integrity": "sha512-ldteZwWIgl9cOy7FyvYn+39Ah4+PfpVE72eYKw75iy2L0zTbhbcwvzeJ5IOu6DQP93bjfXq0NGHY6FYtmYoqFQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/events": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
"async-limiter": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
||||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "4.2.2",
|
||||
|
|
@ -51,30 +32,15 @@
|
|||
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz",
|
||||
"integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==",
|
||||
"requires": {
|
||||
"original": "^1.0.0"
|
||||
"original": "1.0.2"
|
||||
}
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz",
|
||||
"integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw=="
|
||||
},
|
||||
"original": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
|
||||
"integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
|
||||
"requires": {
|
||||
"url-parse": "^1.4.3"
|
||||
"url-parse": "1.4.3"
|
||||
}
|
||||
},
|
||||
"querystringify": {
|
||||
|
|
@ -87,38 +53,22 @@
|
|||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
|
||||
},
|
||||
"typedarray-to-buffer": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
||||
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
||||
"requires": {
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz",
|
||||
"integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==",
|
||||
"requires": {
|
||||
"querystringify": "^2.0.0",
|
||||
"requires-port": "^1.0.0"
|
||||
"querystringify": "2.0.0",
|
||||
"requires-port": "1.0.0"
|
||||
}
|
||||
},
|
||||
"websocket": {
|
||||
"version": "1.0.26",
|
||||
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.26.tgz",
|
||||
"integrity": "sha512-fjcrYDPIQxpTnqFQ9JjxUQcdvR89MFAOjPBlF+vjOt49w/XW4fJknUoMz/mDIn2eK1AdslVojcaOxOqyZZV8rw==",
|
||||
"ws": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.0.0.tgz",
|
||||
"integrity": "sha512-c2UlYcAZp1VS8AORtpq6y4RJIkJ9dQz18W32SpR/qXGfLDZ2jU4y4wKvvZwqbi7U6gxFQTeE+urMbXU/tsDy4w==",
|
||||
"requires": {
|
||||
"debug": "^2.2.0",
|
||||
"nan": "^2.3.3",
|
||||
"typedarray-to-buffer": "^3.1.2",
|
||||
"yaeti": "^0.0.6"
|
||||
"async-limiter": "1.0.0"
|
||||
}
|
||||
},
|
||||
"yaeti": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
|
||||
"integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,11 +37,11 @@
|
|||
],
|
||||
"devDependencies": {
|
||||
"es6-promise": "^4.2.2",
|
||||
"@types/websocket": "^0.0.40",
|
||||
"@types/node": "^10.9.4",
|
||||
"@types/eventsource": "^1.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"websocket": "^1.0.26",
|
||||
"ws": "^6.0.0",
|
||||
"eventsource": "^1.0.7"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
import { TextMessageFormat } from "./TextMessageFormat";
|
||||
import { isArrayBuffer } from "./Utils";
|
||||
|
||||
/** @private */
|
||||
export interface HandshakeRequestMessage {
|
||||
|
|
@ -27,7 +28,7 @@ export class HandshakeProtocol {
|
|||
let messageData: string;
|
||||
let remainingData: any;
|
||||
|
||||
if (data instanceof ArrayBuffer || (typeof Buffer !== "undefined" && data instanceof Buffer)) {
|
||||
if (isArrayBuffer(data) || (typeof Buffer !== "undefined" && data instanceof Buffer)) {
|
||||
// Format is binary but still need to read JSON text from handshake response
|
||||
const binaryData = new Uint8Array(data);
|
||||
const separatorIndex = binaryData.indexOf(TextMessageFormat.RecordSeparatorCode);
|
||||
|
|
@ -56,7 +57,11 @@ export class HandshakeProtocol {
|
|||
|
||||
// At this point we should have just the single handshake message
|
||||
const messages = TextMessageFormat.parse(messageData);
|
||||
responseMessage = JSON.parse(messages[0]);
|
||||
const response = JSON.parse(messages[0]);
|
||||
if (response.type) {
|
||||
throw new Error("Expected a handshake response from the server.");
|
||||
}
|
||||
responseMessage = response;
|
||||
|
||||
// multiple messages could have arrived with handshake
|
||||
// return additional data to be parsed as usual, or null if all parsed
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ let WebSocketModule: any = null;
|
|||
let EventSourceModule: any = null;
|
||||
if (typeof window === "undefined" && typeof require !== "undefined") {
|
||||
// tslint:disable-next-line:no-var-requires
|
||||
WebSocketModule = require("websocket");
|
||||
WebSocketModule = require("ws");
|
||||
// tslint:disable-next-line:no-var-requires
|
||||
EventSourceModule = require("eventsource");
|
||||
}
|
||||
|
|
@ -73,9 +73,8 @@ export class HttpConnection implements IConnection {
|
|||
if (!isNode && typeof WebSocket !== "undefined" && !options.WebSocket) {
|
||||
options.WebSocket = WebSocket;
|
||||
} else if (isNode && !options.WebSocket) {
|
||||
const websocket = WebSocketModule && WebSocketModule.w3cwebsocket;
|
||||
if (websocket) {
|
||||
options.WebSocket = WebSocketModule.w3cwebsocket;
|
||||
if (WebSocketModule) {
|
||||
options.WebSocket = WebSocketModule;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ export class HubConnection {
|
|||
private id: number;
|
||||
private closedCallbacks: Array<(error?: Error) => void>;
|
||||
private receivedHandshakeResponse: boolean;
|
||||
private handshakeResolver!: (value?: PromiseLike<{}>) => void;
|
||||
private handshakeRejecter!: (reason?: any) => void;
|
||||
private connectionState: HubConnectionState;
|
||||
|
||||
// The type of these a) doesn't matter and b) varies when building in browser and node contexts
|
||||
|
|
@ -106,6 +108,11 @@ export class HubConnection {
|
|||
this.logger.log(LogLevel.Debug, "Starting HubConnection.");
|
||||
|
||||
this.receivedHandshakeResponse = false;
|
||||
// Set up the promise before any connection is started otherwise it could race with received messages
|
||||
const handshakePromise = new Promise((resolve, reject) => {
|
||||
this.handshakeResolver = resolve;
|
||||
this.handshakeRejecter = reject;
|
||||
});
|
||||
|
||||
await this.connection.start(this.protocol.transferFormat);
|
||||
|
||||
|
|
@ -120,6 +127,8 @@ export class HubConnection {
|
|||
this.resetTimeoutPeriod();
|
||||
this.resetKeepAliveInterval();
|
||||
|
||||
// Wait for the handshake to complete before marking connection as connected
|
||||
await handshakePromise;
|
||||
this.connectionState = HubConnectionState.Connected;
|
||||
}
|
||||
|
||||
|
|
@ -388,19 +397,23 @@ export class HubConnection {
|
|||
// We don't want to wait on the stop itself.
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
this.connection.stop(error);
|
||||
this.handshakeRejecter(error);
|
||||
throw error;
|
||||
}
|
||||
if (responseMessage.error) {
|
||||
const message = "Server returned handshake error: " + responseMessage.error;
|
||||
this.logger.log(LogLevel.Error, message);
|
||||
|
||||
this.handshakeRejecter(message);
|
||||
// We don't want to wait on the stop itself.
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
this.connection.stop(new Error(message));
|
||||
throw new Error(message);
|
||||
} else {
|
||||
this.logger.log(LogLevel.Debug, "Server handshake complete.");
|
||||
}
|
||||
|
||||
this.handshakeResolver();
|
||||
return remainingData;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { URL } from "url";
|
|||
import { AbortError, HttpError, TimeoutError } from "./Errors";
|
||||
import { HttpClient, HttpRequest, HttpResponse } from "./HttpClient";
|
||||
import { ILogger, LogLevel } from "./ILogger";
|
||||
import { isArrayBuffer } from "./Utils";
|
||||
|
||||
export class NodeHttpClient extends HttpClient {
|
||||
private readonly logger: ILogger;
|
||||
|
|
@ -80,7 +81,7 @@ export class NodeHttpClient extends HttpClient {
|
|||
reject(e);
|
||||
});
|
||||
|
||||
if (request.content instanceof ArrayBuffer) {
|
||||
if (isArrayBuffer(request.content)) {
|
||||
req.write(Buffer.from(request.content));
|
||||
} else {
|
||||
req.write(request.content || "");
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export class Arg {
|
|||
/** @private */
|
||||
export function getDataDetail(data: any, includeContent: boolean): string {
|
||||
let detail = "";
|
||||
if (data instanceof ArrayBuffer) {
|
||||
if (isArrayBuffer(data)) {
|
||||
detail = `Binary data of length ${data.byteLength}`;
|
||||
if (includeContent) {
|
||||
detail += `. Content: '${formatArrayBuffer(data)}'`;
|
||||
|
|
@ -54,6 +54,15 @@ export function formatArrayBuffer(data: ArrayBuffer): string {
|
|||
return str.substr(0, str.length - 1);
|
||||
}
|
||||
|
||||
// Also in signalr-protocol-msgpack/Utils.ts
|
||||
/** @private */
|
||||
export function isArrayBuffer(val: any): val is ArrayBuffer {
|
||||
return val && typeof ArrayBuffer !== "undefined" &&
|
||||
(val instanceof ArrayBuffer ||
|
||||
// Sometimes we get an ArrayBuffer that doesn't satisfy instanceof
|
||||
(val.constructor && val.constructor.name === "ArrayBuffer"));
|
||||
}
|
||||
|
||||
/** @private */
|
||||
export async function sendMessage(logger: ILogger, transportName: string, httpClient: HttpClient, url: string, accessTokenFactory: (() => string | Promise<string>) | undefined, content: string | ArrayBuffer, logMessageContent: boolean): Promise<void> {
|
||||
let headers;
|
||||
|
|
@ -68,7 +77,7 @@ export async function sendMessage(logger: ILogger, transportName: string, httpCl
|
|||
|
||||
logger.log(LogLevel.Trace, `(${transportName} transport) sending data. ${getDataDetail(content, logMessageContent)}.`);
|
||||
|
||||
const responseType = content instanceof ArrayBuffer ? "arraybuffer" : "text";
|
||||
const responseType = isArrayBuffer(content) ? "arraybuffer" : "text";
|
||||
const response = await httpClient.post(url, {
|
||||
content,
|
||||
headers,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ registerUnhandledRejectionHandler();
|
|||
describe("HubConnection", () => {
|
||||
|
||||
describe("start", () => {
|
||||
it("sends negotiation message", async () => {
|
||||
it("sends handshake message", async () => {
|
||||
await VerifyLogger.run(async (logger) => {
|
||||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
|
|
@ -163,12 +163,16 @@ describe("HubConnection", () => {
|
|||
protocolCalled = true;
|
||||
};
|
||||
|
||||
const connection = new TestConnection();
|
||||
const connection = new TestConnection(false);
|
||||
const hubConnection = createHubConnection(connection, logger, mockProtocol);
|
||||
try {
|
||||
let startCompleted = false;
|
||||
const startPromise = hubConnection.start().then(() => startCompleted = true);
|
||||
const data = "{}" + TextMessageFormat.RecordSeparator;
|
||||
expect(startCompleted).toBe(false);
|
||||
|
||||
connection.receiveText(data);
|
||||
await startPromise;
|
||||
|
||||
// message only contained handshake response
|
||||
expect(protocolCalled).toEqual(false);
|
||||
|
|
@ -187,13 +191,18 @@ describe("HubConnection", () => {
|
|||
protocolCalled = true;
|
||||
};
|
||||
|
||||
const connection = new TestConnection();
|
||||
const connection = new TestConnection(false);
|
||||
const hubConnection = createHubConnection(connection, logger, mockProtocol);
|
||||
try {
|
||||
let startCompleted = false;
|
||||
const startPromise = hubConnection.start().then(() => startCompleted = true);
|
||||
expect(startCompleted).toBe(false);
|
||||
|
||||
// handshake response + message separator
|
||||
const data = [0x7b, 0x7d, 0x1e];
|
||||
|
||||
connection.receiveBinary(new Uint8Array(data).buffer);
|
||||
await startPromise;
|
||||
|
||||
// message only contained handshake response
|
||||
expect(protocolCalled).toEqual(false);
|
||||
|
|
@ -210,9 +219,13 @@ describe("HubConnection", () => {
|
|||
const mockProtocol = new TestProtocol(TransferFormat.Binary);
|
||||
mockProtocol.onreceive = (d) => receivedProcotolData = d as ArrayBuffer;
|
||||
|
||||
const connection = new TestConnection();
|
||||
const connection = new TestConnection(false);
|
||||
const hubConnection = createHubConnection(connection, logger, mockProtocol);
|
||||
try {
|
||||
let startCompleted = false;
|
||||
const startPromise = hubConnection.start().then(() => startCompleted = true);
|
||||
expect(startCompleted).toBe(false);
|
||||
|
||||
// handshake response + message separator + message pack message
|
||||
const data = [
|
||||
0x7b, 0x7d, 0x1e, 0x65, 0x95, 0x03, 0x80, 0xa1, 0x30, 0x01, 0xd9, 0x5d, 0x54, 0x68, 0x65, 0x20, 0x63, 0x6c,
|
||||
|
|
@ -224,6 +237,7 @@ describe("HubConnection", () => {
|
|||
];
|
||||
|
||||
connection.receiveBinary(new Uint8Array(data).buffer);
|
||||
await startPromise;
|
||||
|
||||
// left over data is the message pack message
|
||||
expect(receivedProcotolData!.byteLength).toEqual(102);
|
||||
|
|
@ -240,12 +254,17 @@ describe("HubConnection", () => {
|
|||
const mockProtocol = new TestProtocol(TransferFormat.Text);
|
||||
mockProtocol.onreceive = (d) => receivedProcotolData = d as string;
|
||||
|
||||
const connection = new TestConnection();
|
||||
const connection = new TestConnection(false);
|
||||
const hubConnection = createHubConnection(connection, logger, mockProtocol);
|
||||
try {
|
||||
let startCompleted = false;
|
||||
const startPromise = hubConnection.start().then(() => startCompleted = true);
|
||||
expect(startCompleted).toBe(false);
|
||||
|
||||
const data = "{}" + TextMessageFormat.RecordSeparator + "{\"type\":6}" + TextMessageFormat.RecordSeparator;
|
||||
|
||||
connection.receiveText(data);
|
||||
await startPromise;
|
||||
|
||||
expect(receivedProcotolData).toEqual("{\"type\":6}" + TextMessageFormat.RecordSeparator);
|
||||
} finally {
|
||||
|
|
@ -259,7 +278,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
const invokePromise = hubConnection.invoke("testMethod", "arg", 42);
|
||||
|
||||
|
|
@ -277,7 +296,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
const invokePromise = hubConnection.invoke("testMethod", "arg", 42);
|
||||
|
||||
|
|
@ -296,7 +315,7 @@ describe("HubConnection", () => {
|
|||
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
const invokePromise = hubConnection.invoke("testMethod");
|
||||
await hubConnection.stop();
|
||||
|
|
@ -311,7 +330,7 @@ describe("HubConnection", () => {
|
|||
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
const invokePromise = hubConnection.invoke("testMethod");
|
||||
// Typically this would be called by the transport
|
||||
|
|
@ -340,7 +359,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, wrappingLogger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
connection.receive({
|
||||
arguments: ["test"],
|
||||
|
|
@ -370,7 +389,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, wrappingLogger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
const handler = () => { };
|
||||
hubConnection.on("message", handler);
|
||||
|
|
@ -396,7 +415,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
let count = 0;
|
||||
const handler = () => { count++; };
|
||||
|
|
@ -432,7 +451,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
let count = 0;
|
||||
const handler = () => { count++; };
|
||||
|
|
@ -468,7 +487,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
let count = 0;
|
||||
const handler = () => { count++; };
|
||||
|
|
@ -494,7 +513,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
let value = "";
|
||||
hubConnection.on("message", (v) => value = v);
|
||||
|
|
@ -515,13 +534,22 @@ describe("HubConnection", () => {
|
|||
|
||||
it("stop on handshake error", async () => {
|
||||
await VerifyLogger.run(async (logger) => {
|
||||
const connection = new TestConnection();
|
||||
const connection = new TestConnection(false);
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
let closeError: Error | undefined;
|
||||
hubConnection.onclose((e) => closeError = e);
|
||||
|
||||
connection.receiveHandshakeResponse("Error!");
|
||||
let startCompleted = false;
|
||||
const startPromise = hubConnection.start().then(() => startCompleted = true);
|
||||
expect(startCompleted).toBe(false);
|
||||
try {
|
||||
connection.receiveHandshakeResponse("Error!");
|
||||
} catch {
|
||||
}
|
||||
await expect(startPromise)
|
||||
.rejects
|
||||
.toThrow("Server returned handshake error: Error!");
|
||||
|
||||
expect(closeError!.message).toEqual("Server returned handshake error: Error!");
|
||||
} finally {
|
||||
|
|
@ -543,7 +571,7 @@ describe("HubConnection", () => {
|
|||
closeError = e;
|
||||
});
|
||||
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
connection.receive({
|
||||
type: MessageType.Close,
|
||||
|
|
@ -569,7 +597,7 @@ describe("HubConnection", () => {
|
|||
closeError = e;
|
||||
});
|
||||
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
connection.receive({
|
||||
error: "Error!",
|
||||
|
|
@ -589,7 +617,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
let numInvocations1 = 0;
|
||||
let numInvocations2 = 0;
|
||||
|
|
@ -616,7 +644,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
let numInvocations = 0;
|
||||
const callback = () => numInvocations++;
|
||||
|
|
@ -674,7 +702,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, wrappingLogger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
hubConnection.on(null!, undefined!);
|
||||
hubConnection.on(undefined!, null!);
|
||||
|
|
@ -714,11 +742,13 @@ describe("HubConnection", () => {
|
|||
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
await hubConnection.start();
|
||||
|
||||
hubConnection.stream("testStream", "arg", 42);
|
||||
|
||||
// Verify the message is sent
|
||||
expect(connection.sentData.length).toBe(1);
|
||||
expect(JSON.parse(connection.sentData[0])).toEqual({
|
||||
// Verify the message is sent (+ handshake)
|
||||
expect(connection.sentData.length).toBe(2);
|
||||
expect(JSON.parse(connection.sentData[1])).toEqual({
|
||||
arguments: [
|
||||
"arg",
|
||||
42,
|
||||
|
|
@ -741,7 +771,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
const observer = new TestObserver();
|
||||
hubConnection.stream<any>("testMethod", "arg", 42)
|
||||
|
|
@ -761,7 +791,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
const observer = new TestObserver();
|
||||
hubConnection.stream<any>("testMethod", "arg", 42)
|
||||
|
|
@ -782,6 +812,8 @@ describe("HubConnection", () => {
|
|||
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
await hubConnection.start();
|
||||
|
||||
const observer = new TestObserver();
|
||||
hubConnection.stream<any>("testMethod")
|
||||
.subscribe(observer);
|
||||
|
|
@ -800,6 +832,8 @@ describe("HubConnection", () => {
|
|||
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
await hubConnection.start();
|
||||
|
||||
const observer = new TestObserver();
|
||||
hubConnection.stream<any>("testMethod")
|
||||
.subscribe(observer);
|
||||
|
|
@ -819,7 +853,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
const observer = new TestObserver();
|
||||
hubConnection.stream<any>("testMethod")
|
||||
|
|
@ -848,6 +882,7 @@ describe("HubConnection", () => {
|
|||
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
await hubConnection.start();
|
||||
hubConnection.stream("testMethod").subscribe(NullSubscriber.instance);
|
||||
|
||||
// Typically this would be called by the transport
|
||||
|
|
@ -865,6 +900,7 @@ describe("HubConnection", () => {
|
|||
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
await hubConnection.start();
|
||||
hubConnection.stream("testMethod").subscribe(NullSubscriber.instance);
|
||||
|
||||
// Send completion to trigger observer.complete()
|
||||
|
|
@ -881,7 +917,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
connection.receiveHandshakeResponse();
|
||||
await hubConnection.start();
|
||||
|
||||
const observer = new TestObserver();
|
||||
const subscription = hubConnection.stream("testMethod")
|
||||
|
|
@ -896,9 +932,9 @@ describe("HubConnection", () => {
|
|||
// Observer should no longer receive messages
|
||||
expect(observer.itemsReceived).toEqual([1]);
|
||||
|
||||
// Verify the cancel is sent
|
||||
expect(connection.sentData.length).toBe(2);
|
||||
expect(JSON.parse(connection.sentData[1])).toEqual({
|
||||
// Verify the cancel is sent (+ handshake)
|
||||
expect(connection.sentData.length).toBe(3);
|
||||
expect(JSON.parse(connection.sentData[2])).toEqual({
|
||||
invocationId: connection.lastInvocationId,
|
||||
type: MessageType.CancelInvocation,
|
||||
});
|
||||
|
|
@ -986,6 +1022,7 @@ describe("HubConnection", () => {
|
|||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
await hubConnection.start();
|
||||
const invokePromise = hubConnection.invoke("testMethod", "arg", 42);
|
||||
|
||||
connection.receive({ type: MessageType.Ping });
|
||||
|
|
@ -1025,37 +1062,6 @@ describe("HubConnection", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("does not timeout if message was received before HubConnection.start", async () => {
|
||||
await VerifyLogger.run(async (logger) => {
|
||||
const connection = new TestConnection();
|
||||
const hubConnection = createHubConnection(connection, logger);
|
||||
try {
|
||||
hubConnection.serverTimeoutInMilliseconds = 200;
|
||||
|
||||
const p = new PromiseSource<Error>();
|
||||
hubConnection.onclose((e) => p.resolve(e));
|
||||
|
||||
// send message before start to trigger timeout handler
|
||||
// testing for regression where we didn't cleanup timer if request received before start created a timer
|
||||
await connection.receive({ type: MessageType.Ping });
|
||||
|
||||
await hubConnection.start();
|
||||
|
||||
for (let i = 0; i < 6; i++) {
|
||||
await pingAndWait(connection);
|
||||
}
|
||||
|
||||
await connection.stop();
|
||||
|
||||
const error = await p.promise;
|
||||
|
||||
expect(error).toBeUndefined();
|
||||
} finally {
|
||||
await hubConnection.stop();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("terminates if no messages received within timeout interval", async () => {
|
||||
await VerifyLogger.run(async (logger) => {
|
||||
const connection = new TestConnection();
|
||||
|
|
@ -1092,11 +1098,14 @@ class TestConnection implements IConnection {
|
|||
public sentData: any[];
|
||||
public lastInvocationId: string | null;
|
||||
|
||||
constructor() {
|
||||
private autoHandshake: boolean | null;
|
||||
|
||||
constructor(autoHandshake: boolean = true) {
|
||||
this.onreceive = null;
|
||||
this.onclose = null;
|
||||
this.sentData = [];
|
||||
this.lastInvocationId = null;
|
||||
this.autoHandshake = autoHandshake;
|
||||
}
|
||||
|
||||
public start(): Promise<void> {
|
||||
|
|
@ -1105,7 +1114,11 @@ class TestConnection implements IConnection {
|
|||
|
||||
public send(data: any): Promise<void> {
|
||||
const invocation = TextMessageFormat.parse(data)[0];
|
||||
const invocationId = JSON.parse(invocation).invocationId;
|
||||
const parsedInvocation = JSON.parse(invocation);
|
||||
const invocationId = parsedInvocation.invocationId;
|
||||
if (parsedInvocation.protocol && parsedInvocation.version && this.autoHandshake) {
|
||||
this.receiveHandshakeResponse();
|
||||
}
|
||||
if (invocationId) {
|
||||
this.lastInvocationId = invocationId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,10 @@ describe("HubConnectionBuilder", () => {
|
|||
|
||||
// Start the connection
|
||||
const closed = makeClosedPromise(connection);
|
||||
await connection.start();
|
||||
|
||||
// start waits for handshake before returning, we don't care in this test
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
connection.start();
|
||||
|
||||
const pollRequest = await pollSent.promise;
|
||||
expect(pollRequest.url).toMatch(/http:\/\/example.com\?id=abc123.*/);
|
||||
|
|
@ -109,7 +112,10 @@ describe("HubConnectionBuilder", () => {
|
|||
|
||||
// Start the connection
|
||||
const closed = makeClosedPromise(connection);
|
||||
await connection.start();
|
||||
|
||||
// start waits for handshake before returning, we don't care in this test
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
connection.start();
|
||||
|
||||
const negotiateRequest = await negotiateReceived.promise;
|
||||
expect(negotiateRequest.content).toBe(`{"protocol":"${protocol.name}","version":1}\x1E`);
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ module.exports = function (modulePath, browserBaseName, options) {
|
|||
new webpack.IgnorePlugin(/vertx/),
|
||||
new webpack.IgnorePlugin(/NodeHttpClient/),
|
||||
new webpack.IgnorePlugin(/eventsource/),
|
||||
new webpack.IgnorePlugin(/websocket/),
|
||||
],
|
||||
externals: options.externals,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
|
|||
case TypePropertyName:
|
||||
// a handshake response does not have a type
|
||||
// check the incoming message was not any other type of message
|
||||
throw new InvalidDataException("Handshake response should not have a 'type' value.");
|
||||
throw new InvalidDataException("Expected a handshake response from the server.");
|
||||
case ErrorPropertyName:
|
||||
error = JsonUtils.ReadAsString(reader, ErrorPropertyName);
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue