@aspnet/signalr
Advanced tools
Comparing version 1.1.0-preview3-35497 to 1.1.0
@@ -20,4 +20,6 @@ "use strict"; | ||
if (typeof XMLHttpRequest === "undefined") { | ||
// tslint:disable-next-line:no-var-requires | ||
nodeHttpClientModule = require("./NodeHttpClient"); | ||
// In order to ignore the dynamic require in webpack builds we need to do this magic | ||
// @ts-ignore: TS doesn't know about these names | ||
var requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require; | ||
nodeHttpClientModule = requireFunc("./NodeHttpClient"); | ||
} | ||
@@ -55,2 +57,5 @@ /** Default implementation of {@link @aspnet/signalr.HttpClient}. */ | ||
}; | ||
DefaultHttpClient.prototype.getCookieString = function (url) { | ||
return this.httpClient.getCookieString(url); | ||
}; | ||
return DefaultHttpClient; | ||
@@ -57,0 +62,0 @@ }(HttpClient_1.HttpClient)); |
@@ -39,2 +39,11 @@ "use strict"; | ||
}; | ||
/** Gets all cookies that apply to the specified URL. | ||
* | ||
* @param url The URL that the cookies are valid for. | ||
* @returns {string} A string containing all the key-value cookie pairs for the specified URL. | ||
*/ | ||
// @ts-ignore | ||
HttpClient.prototype.getCookieString = function (url) { | ||
return ""; | ||
}; | ||
return HttpClient; | ||
@@ -41,0 +50,0 @@ }()); |
@@ -51,6 +51,7 @@ "use strict"; | ||
if (typeof window === "undefined" && typeof require !== "undefined") { | ||
// tslint:disable-next-line:no-var-requires | ||
WebSocketModule = require("ws"); | ||
// tslint:disable-next-line:no-var-requires | ||
EventSourceModule = require("eventsource"); | ||
// In order to ignore the dynamic require in webpack builds we need to do this magic | ||
// @ts-ignore: TS doesn't know about these names | ||
var requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require; | ||
WebSocketModule = requireFunc("ws"); | ||
EventSourceModule = requireFunc("eventsource"); | ||
} | ||
@@ -257,3 +258,3 @@ /** @private */ | ||
negotiateUrl = this.resolveNegotiateUrl(url); | ||
this.logger.log(ILogger_1.LogLevel.Debug, "Sending negotiation request: " + negotiateUrl); | ||
this.logger.log(ILogger_1.LogLevel.Debug, "Sending negotiation request: " + negotiateUrl + "."); | ||
_b.label = 3; | ||
@@ -348,3 +349,3 @@ case 3: | ||
} | ||
return new WebSocketTransport_1.WebSocketTransport(this.accessTokenFactory, this.logger, this.options.logMessageContent || false, this.options.WebSocket); | ||
return new WebSocketTransport_1.WebSocketTransport(this.httpClient, this.accessTokenFactory, this.logger, this.options.logMessageContent || false, this.options.WebSocket); | ||
case ITransport_1.HttpTransportType.ServerSentEvents: | ||
@@ -375,3 +376,3 @@ if (!this.options.EventSource) { | ||
else { | ||
this.logger.log(ILogger_1.LogLevel.Debug, "Selecting transport '" + ITransport_1.HttpTransportType[transport] + "'"); | ||
this.logger.log(ILogger_1.LogLevel.Debug, "Selecting transport '" + ITransport_1.HttpTransportType[transport] + "'."); | ||
return transport; | ||
@@ -378,0 +379,0 @@ } |
@@ -353,3 +353,3 @@ "use strict"; | ||
default: | ||
this.logger.log(ILogger_1.LogLevel.Warning, "Invalid message type: " + message.type); | ||
this.logger.log(ILogger_1.LogLevel.Warning, "Invalid message type: " + message.type + "."); | ||
break; | ||
@@ -356,0 +356,0 @@ } |
@@ -7,3 +7,3 @@ "use strict"; | ||
/** The version of the SignalR client. */ | ||
exports.VERSION = "1.1.0-preview3-35497"; | ||
exports.VERSION = "1.1.0"; | ||
var Errors_1 = require("./Errors"); | ||
@@ -10,0 +10,0 @@ exports.AbortError = Errors_1.AbortError; |
@@ -76,3 +76,3 @@ "use strict"; | ||
this.url = url; | ||
this.logger.log(ILogger_1.LogLevel.Trace, "(LongPolling transport) Connecting"); | ||
this.logger.log(ILogger_1.LogLevel.Trace, "(LongPolling transport) Connecting."); | ||
// Allow binary format on Node and Browsers that support binary content (indicated by the presence of responseType property) | ||
@@ -96,3 +96,3 @@ if (transferFormat === ITransport_1.TransferFormat.Binary && | ||
pollUrl = url + "&_=" + Date.now(); | ||
this.logger.log(ILogger_1.LogLevel.Trace, "(LongPolling transport) polling: " + pollUrl); | ||
this.logger.log(ILogger_1.LogLevel.Trace, "(LongPolling transport) polling: " + pollUrl + "."); | ||
return [4 /*yield*/, this.httpClient.get(pollUrl, pollOptions)]; | ||
@@ -102,3 +102,3 @@ case 2: | ||
if (response.statusCode !== 200) { | ||
this.logger.log(ILogger_1.LogLevel.Error, "(LongPolling transport) Unexpected response code: " + response.statusCode); | ||
this.logger.log(ILogger_1.LogLevel.Error, "(LongPolling transport) Unexpected response code: " + response.statusCode + "."); | ||
// Mark running as false so that the poll immediately ends and runs the close logic | ||
@@ -163,3 +163,3 @@ this.closeError = new Errors_1.HttpError(response.statusText || "", response.statusCode); | ||
pollUrl = url + "&_=" + Date.now(); | ||
this.logger.log(ILogger_1.LogLevel.Trace, "(LongPolling transport) polling: " + pollUrl); | ||
this.logger.log(ILogger_1.LogLevel.Trace, "(LongPolling transport) polling: " + pollUrl + "."); | ||
return [4 /*yield*/, this.httpClient.get(pollUrl, pollOptions)]; | ||
@@ -169,7 +169,7 @@ case 4: | ||
if (response.statusCode === 204) { | ||
this.logger.log(ILogger_1.LogLevel.Information, "(LongPolling transport) Poll terminated by server"); | ||
this.logger.log(ILogger_1.LogLevel.Information, "(LongPolling transport) Poll terminated by server."); | ||
this.running = false; | ||
} | ||
else if (response.statusCode !== 200) { | ||
this.logger.log(ILogger_1.LogLevel.Error, "(LongPolling transport) Unexpected response code: " + response.statusCode); | ||
this.logger.log(ILogger_1.LogLevel.Error, "(LongPolling transport) Unexpected response code: " + response.statusCode + "."); | ||
// Unexpected status code | ||
@@ -182,3 +182,3 @@ this.closeError = new Errors_1.HttpError(response.statusText || "", response.statusCode); | ||
if (response.content) { | ||
this.logger.log(ILogger_1.LogLevel.Trace, "(LongPolling transport) data received. " + Utils_1.getDataDetail(response.content, this.logMessageContent)); | ||
this.logger.log(ILogger_1.LogLevel.Trace, "(LongPolling transport) data received. " + Utils_1.getDataDetail(response.content, this.logMessageContent) + "."); | ||
if (this.onreceive) { | ||
@@ -185,0 +185,0 @@ this.onreceive(response.content); |
@@ -23,4 +23,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var http = require("http"); | ||
var url_1 = require("url"); | ||
var Request = require("request"); | ||
var Errors_1 = require("./Errors"); | ||
@@ -35,71 +34,56 @@ var HttpClient_1 = require("./HttpClient"); | ||
_this.logger = logger; | ||
_this.cookieJar = Request.jar(); | ||
_this.request = Request.defaults({ jar: _this.cookieJar }); | ||
return _this; | ||
} | ||
NodeHttpClient.prototype.send = function (request) { | ||
NodeHttpClient.prototype.send = function (httpRequest) { | ||
var _this = this; | ||
return new Promise(function (resolve, reject) { | ||
var url = new url_1.URL(request.url); | ||
var options = { | ||
var requestBody; | ||
if (Utils_1.isArrayBuffer(httpRequest.content)) { | ||
requestBody = Buffer.from(httpRequest.content); | ||
} | ||
else { | ||
requestBody = httpRequest.content || ""; | ||
} | ||
var currentRequest = _this.request(httpRequest.url, { | ||
body: requestBody, | ||
// If binary is expected 'null' should be used, otherwise for text 'utf8' | ||
encoding: httpRequest.responseType === "arraybuffer" ? null : "utf8", | ||
headers: __assign({ | ||
// Tell auth middleware to 401 instead of redirecting | ||
"X-Requested-With": "XMLHttpRequest" }, request.headers), | ||
hostname: url.hostname, | ||
method: request.method, | ||
// /abc/xyz + ?id=12ssa_30 | ||
path: url.pathname + url.search, | ||
port: url.port, | ||
}; | ||
var req = http.request(options, function (res) { | ||
var data = []; | ||
var dataLength = 0; | ||
res.on("data", function (chunk) { | ||
data.push(chunk); | ||
// Buffer.concat will be slightly faster if we keep track of the length | ||
dataLength += chunk.length; | ||
}); | ||
res.on("end", function () { | ||
if (request.abortSignal) { | ||
request.abortSignal.onabort = null; | ||
"X-Requested-With": "XMLHttpRequest" }, httpRequest.headers), | ||
method: httpRequest.method, | ||
timeout: httpRequest.timeout, | ||
}, function (error, response, body) { | ||
if (httpRequest.abortSignal) { | ||
httpRequest.abortSignal.onabort = null; | ||
} | ||
if (error) { | ||
if (error.code === "ETIMEDOUT") { | ||
_this.logger.log(ILogger_1.LogLevel.Warning, "Timeout from HTTP request."); | ||
reject(new Errors_1.TimeoutError()); | ||
} | ||
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) { | ||
var resp = void 0; | ||
if (request.responseType === "arraybuffer") { | ||
resp = Buffer.concat(data, dataLength); | ||
resolve(new HttpClient_1.HttpResponse(res.statusCode, res.statusMessage || "", resp)); | ||
} | ||
else { | ||
resp = Buffer.concat(data, dataLength).toString(); | ||
resolve(new HttpClient_1.HttpResponse(res.statusCode, res.statusMessage || "", resp)); | ||
} | ||
} | ||
else { | ||
reject(new Errors_1.HttpError(res.statusMessage || "", res.statusCode || 0)); | ||
} | ||
}); | ||
_this.logger.log(ILogger_1.LogLevel.Warning, "Error from HTTP request. " + error); | ||
reject(error); | ||
return; | ||
} | ||
if (response.statusCode >= 200 && response.statusCode < 300) { | ||
resolve(new HttpClient_1.HttpResponse(response.statusCode, response.statusMessage || "", body)); | ||
} | ||
else { | ||
reject(new Errors_1.HttpError(response.statusMessage || "", response.statusCode || 0)); | ||
} | ||
}); | ||
if (request.abortSignal) { | ||
request.abortSignal.onabort = function () { | ||
req.abort(); | ||
if (httpRequest.abortSignal) { | ||
httpRequest.abortSignal.onabort = function () { | ||
currentRequest.abort(); | ||
reject(new Errors_1.AbortError()); | ||
}; | ||
} | ||
if (request.timeout) { | ||
req.setTimeout(request.timeout, function () { | ||
_this.logger.log(ILogger_1.LogLevel.Warning, "Timeout from HTTP request."); | ||
reject(new Errors_1.TimeoutError()); | ||
}); | ||
} | ||
req.on("error", function (e) { | ||
_this.logger.log(ILogger_1.LogLevel.Warning, "Error from HTTP request. " + e); | ||
reject(e); | ||
}); | ||
if (Utils_1.isArrayBuffer(request.content)) { | ||
req.write(Buffer.from(request.content)); | ||
} | ||
else { | ||
req.write(request.content || ""); | ||
} | ||
req.end(); | ||
}); | ||
}; | ||
NodeHttpClient.prototype.getCookieString = function (url) { | ||
return this.cookieJar.getCookieString(url); | ||
}; | ||
return NodeHttpClient; | ||
@@ -106,0 +90,0 @@ }(HttpClient_1.HttpClient)); |
@@ -64,3 +64,3 @@ "use strict"; | ||
Utils_1.Arg.isIn(transferFormat, ITransport_1.TransferFormat, "transferFormat"); | ||
this.logger.log(ILogger_1.LogLevel.Trace, "(SSE transport) Connecting"); | ||
this.logger.log(ILogger_1.LogLevel.Trace, "(SSE transport) Connecting."); | ||
// set url before accessTokenFactory because this.url is only for send and we set the auth header instead of the query string for send | ||
@@ -82,3 +82,11 @@ this.url = url; | ||
} | ||
var eventSource = new _this.eventSourceConstructor(url, { withCredentials: true }); | ||
var eventSource; | ||
if (typeof window !== "undefined") { | ||
eventSource = new _this.eventSourceConstructor(url, { withCredentials: true }); | ||
} | ||
else { | ||
// Non-browser passes cookies via the dictionary | ||
var cookies = _this.httpClient.getCookieString(url); | ||
eventSource = new _this.eventSourceConstructor(url, { withCredentials: true, headers: { Cookie: cookies } }); | ||
} | ||
try { | ||
@@ -85,0 +93,0 @@ eventSource.onmessage = function (e) { |
@@ -72,3 +72,3 @@ "use strict"; | ||
if (includeContent) { | ||
detail += ". Content: '" + data + "'."; | ||
detail += ". Content: '" + data + "'"; | ||
} | ||
@@ -75,0 +75,0 @@ } |
@@ -45,3 +45,3 @@ "use strict"; | ||
var WebSocketTransport = /** @class */ (function () { | ||
function WebSocketTransport(accessTokenFactory, logger, logMessageContent, webSocketConstructor) { | ||
function WebSocketTransport(httpClient, accessTokenFactory, logger, logMessageContent, webSocketConstructor) { | ||
this.logger = logger; | ||
@@ -51,2 +51,3 @@ this.accessTokenFactory = accessTokenFactory; | ||
this.webSocketConstructor = webSocketConstructor; | ||
this.httpClient = httpClient; | ||
this.onreceive = null; | ||
@@ -65,3 +66,3 @@ this.onclose = null; | ||
Utils_1.Arg.isIn(transferFormat, ITransport_1.TransferFormat, "transferFormat"); | ||
this.logger.log(ILogger_1.LogLevel.Trace, "(WebSockets transport) Connecting"); | ||
this.logger.log(ILogger_1.LogLevel.Trace, "(WebSockets transport) Connecting."); | ||
if (!this.accessTokenFactory) return [3 /*break*/, 2]; | ||
@@ -77,3 +78,16 @@ return [4 /*yield*/, this.accessTokenFactory()]; | ||
url = url.replace(/^http/, "ws"); | ||
var webSocket = new _this.webSocketConstructor(url); | ||
var webSocket; | ||
var cookies = _this.httpClient.getCookieString(url); | ||
if (typeof window === "undefined" && cookies) { | ||
// Only pass cookies when in non-browser environments | ||
webSocket = new _this.webSocketConstructor(url, undefined, { | ||
headers: { | ||
Cookie: "" + cookies, | ||
}, | ||
}); | ||
} | ||
if (!webSocket) { | ||
// Chrome is not happy with passing 'undefined' as protocol | ||
webSocket = new _this.webSocketConstructor(url); | ||
} | ||
if (transferFormat === ITransport_1.TransferFormat.Binary) { | ||
@@ -84,3 +98,3 @@ webSocket.binaryType = "arraybuffer"; | ||
webSocket.onopen = function (_event) { | ||
_this.logger.log(ILogger_1.LogLevel.Information, "WebSocket connected to " + url); | ||
_this.logger.log(ILogger_1.LogLevel.Information, "WebSocket connected to " + url + "."); | ||
_this.webSocket = webSocket; | ||
@@ -136,3 +150,3 @@ resolve(); | ||
if (event && (event.wasClean === false || event.code !== 1000)) { | ||
this.onclose(new Error("Websocket closed with status code: " + event.code + " (" + event.reason + ")")); | ||
this.onclose(new Error("WebSocket closed with status code: " + event.code + " (" + event.reason + ").")); | ||
} | ||
@@ -139,0 +153,0 @@ else { |
@@ -76,3 +76,3 @@ "use strict"; | ||
xhr.onerror = function () { | ||
_this.logger.log(ILogger_1.LogLevel.Warning, "Error from HTTP request. " + xhr.status + ": " + xhr.statusText); | ||
_this.logger.log(ILogger_1.LogLevel.Warning, "Error from HTTP request. " + xhr.status + ": " + xhr.statusText + "."); | ||
reject(new Errors_1.HttpError(xhr.statusText, xhr.status)); | ||
@@ -79,0 +79,0 @@ }; |
@@ -10,2 +10,3 @@ import { HttpClient, HttpRequest, HttpResponse } from "./HttpClient"; | ||
send(request: HttpRequest): Promise<HttpResponse>; | ||
getCookieString(url: string): string; | ||
} |
@@ -18,4 +18,6 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
if (typeof XMLHttpRequest === "undefined") { | ||
// tslint:disable-next-line:no-var-requires | ||
nodeHttpClientModule = require("./NodeHttpClient"); | ||
// In order to ignore the dynamic require in webpack builds we need to do this magic | ||
// @ts-ignore: TS doesn't know about these names | ||
var requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require; | ||
nodeHttpClientModule = requireFunc("./NodeHttpClient"); | ||
} | ||
@@ -53,2 +55,5 @@ /** Default implementation of {@link @aspnet/signalr.HttpClient}. */ | ||
}; | ||
DefaultHttpClient.prototype.getCookieString = function (url) { | ||
return this.httpClient.getCookieString(url); | ||
}; | ||
return DefaultHttpClient; | ||
@@ -55,0 +60,0 @@ }(HttpClient)); |
@@ -102,2 +102,8 @@ import { AbortSignal } from "./AbortController"; | ||
abstract send(request: HttpRequest): Promise<HttpResponse>; | ||
/** Gets all cookies that apply to the specified URL. | ||
* | ||
* @param url The URL that the cookies are valid for. | ||
* @returns {string} A string containing all the key-value cookie pairs for the specified URL. | ||
*/ | ||
getCookieString(url: string): string; | ||
} |
@@ -37,2 +37,11 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
}; | ||
/** Gets all cookies that apply to the specified URL. | ||
* | ||
* @param url The URL that the cookies are valid for. | ||
* @returns {string} A string containing all the key-value cookie pairs for the specified URL. | ||
*/ | ||
// @ts-ignore | ||
HttpClient.prototype.getCookieString = function (url) { | ||
return ""; | ||
}; | ||
return HttpClient; | ||
@@ -39,0 +48,0 @@ }()); |
@@ -49,6 +49,7 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
if (typeof window === "undefined" && typeof require !== "undefined") { | ||
// tslint:disable-next-line:no-var-requires | ||
WebSocketModule = require("ws"); | ||
// tslint:disable-next-line:no-var-requires | ||
EventSourceModule = require("eventsource"); | ||
// In order to ignore the dynamic require in webpack builds we need to do this magic | ||
// @ts-ignore: TS doesn't know about these names | ||
var requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require; | ||
WebSocketModule = requireFunc("ws"); | ||
EventSourceModule = requireFunc("eventsource"); | ||
} | ||
@@ -255,3 +256,3 @@ /** @private */ | ||
negotiateUrl = this.resolveNegotiateUrl(url); | ||
this.logger.log(LogLevel.Debug, "Sending negotiation request: " + negotiateUrl); | ||
this.logger.log(LogLevel.Debug, "Sending negotiation request: " + negotiateUrl + "."); | ||
_b.label = 3; | ||
@@ -346,3 +347,3 @@ case 3: | ||
} | ||
return new WebSocketTransport(this.accessTokenFactory, this.logger, this.options.logMessageContent || false, this.options.WebSocket); | ||
return new WebSocketTransport(this.httpClient, this.accessTokenFactory, this.logger, this.options.logMessageContent || false, this.options.WebSocket); | ||
case HttpTransportType.ServerSentEvents: | ||
@@ -373,3 +374,3 @@ if (!this.options.EventSource) { | ||
else { | ||
this.logger.log(LogLevel.Debug, "Selecting transport '" + HttpTransportType[transport] + "'"); | ||
this.logger.log(LogLevel.Debug, "Selecting transport '" + HttpTransportType[transport] + "'."); | ||
return transport; | ||
@@ -376,0 +377,0 @@ } |
@@ -351,3 +351,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
default: | ||
this.logger.log(LogLevel.Warning, "Invalid message type: " + message.type); | ||
this.logger.log(LogLevel.Warning, "Invalid message type: " + message.type + "."); | ||
break; | ||
@@ -354,0 +354,0 @@ } |
@@ -5,3 +5,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
/** The version of the SignalR client. */ | ||
export var VERSION = "1.1.0-preview3-35497"; | ||
export var VERSION = "1.1.0"; | ||
export { AbortError, HttpError, TimeoutError } from "./Errors"; | ||
@@ -8,0 +8,0 @@ export { HttpClient, HttpResponse } from "./HttpClient"; |
@@ -74,3 +74,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
this.url = url; | ||
this.logger.log(LogLevel.Trace, "(LongPolling transport) Connecting"); | ||
this.logger.log(LogLevel.Trace, "(LongPolling transport) Connecting."); | ||
// Allow binary format on Node and Browsers that support binary content (indicated by the presence of responseType property) | ||
@@ -94,3 +94,3 @@ if (transferFormat === TransferFormat.Binary && | ||
pollUrl = url + "&_=" + Date.now(); | ||
this.logger.log(LogLevel.Trace, "(LongPolling transport) polling: " + pollUrl); | ||
this.logger.log(LogLevel.Trace, "(LongPolling transport) polling: " + pollUrl + "."); | ||
return [4 /*yield*/, this.httpClient.get(pollUrl, pollOptions)]; | ||
@@ -100,3 +100,3 @@ case 2: | ||
if (response.statusCode !== 200) { | ||
this.logger.log(LogLevel.Error, "(LongPolling transport) Unexpected response code: " + response.statusCode); | ||
this.logger.log(LogLevel.Error, "(LongPolling transport) Unexpected response code: " + response.statusCode + "."); | ||
// Mark running as false so that the poll immediately ends and runs the close logic | ||
@@ -161,3 +161,3 @@ this.closeError = new HttpError(response.statusText || "", response.statusCode); | ||
pollUrl = url + "&_=" + Date.now(); | ||
this.logger.log(LogLevel.Trace, "(LongPolling transport) polling: " + pollUrl); | ||
this.logger.log(LogLevel.Trace, "(LongPolling transport) polling: " + pollUrl + "."); | ||
return [4 /*yield*/, this.httpClient.get(pollUrl, pollOptions)]; | ||
@@ -167,7 +167,7 @@ case 4: | ||
if (response.statusCode === 204) { | ||
this.logger.log(LogLevel.Information, "(LongPolling transport) Poll terminated by server"); | ||
this.logger.log(LogLevel.Information, "(LongPolling transport) Poll terminated by server."); | ||
this.running = false; | ||
} | ||
else if (response.statusCode !== 200) { | ||
this.logger.log(LogLevel.Error, "(LongPolling transport) Unexpected response code: " + response.statusCode); | ||
this.logger.log(LogLevel.Error, "(LongPolling transport) Unexpected response code: " + response.statusCode + "."); | ||
// Unexpected status code | ||
@@ -180,3 +180,3 @@ this.closeError = new HttpError(response.statusText || "", response.statusCode); | ||
if (response.content) { | ||
this.logger.log(LogLevel.Trace, "(LongPolling transport) data received. " + getDataDetail(response.content, this.logMessageContent)); | ||
this.logger.log(LogLevel.Trace, "(LongPolling transport) data received. " + getDataDetail(response.content, this.logMessageContent) + "."); | ||
if (this.onreceive) { | ||
@@ -183,0 +183,0 @@ this.onreceive(response.content); |
@@ -5,4 +5,7 @@ import { HttpClient, HttpRequest, HttpResponse } from "./HttpClient"; | ||
private readonly logger; | ||
private readonly request; | ||
private readonly cookieJar; | ||
constructor(logger: ILogger); | ||
send(request: HttpRequest): Promise<HttpResponse>; | ||
send(httpRequest: HttpRequest): Promise<HttpResponse>; | ||
getCookieString(url: string): string; | ||
} |
@@ -21,4 +21,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
}; | ||
import * as http from "http"; | ||
import { URL } from "url"; | ||
import * as Request from "request"; | ||
import { AbortError, HttpError, TimeoutError } from "./Errors"; | ||
@@ -33,71 +32,56 @@ import { HttpClient, HttpResponse } from "./HttpClient"; | ||
_this.logger = logger; | ||
_this.cookieJar = Request.jar(); | ||
_this.request = Request.defaults({ jar: _this.cookieJar }); | ||
return _this; | ||
} | ||
NodeHttpClient.prototype.send = function (request) { | ||
NodeHttpClient.prototype.send = function (httpRequest) { | ||
var _this = this; | ||
return new Promise(function (resolve, reject) { | ||
var url = new URL(request.url); | ||
var options = { | ||
var requestBody; | ||
if (isArrayBuffer(httpRequest.content)) { | ||
requestBody = Buffer.from(httpRequest.content); | ||
} | ||
else { | ||
requestBody = httpRequest.content || ""; | ||
} | ||
var currentRequest = _this.request(httpRequest.url, { | ||
body: requestBody, | ||
// If binary is expected 'null' should be used, otherwise for text 'utf8' | ||
encoding: httpRequest.responseType === "arraybuffer" ? null : "utf8", | ||
headers: __assign({ | ||
// Tell auth middleware to 401 instead of redirecting | ||
"X-Requested-With": "XMLHttpRequest" }, request.headers), | ||
hostname: url.hostname, | ||
method: request.method, | ||
// /abc/xyz + ?id=12ssa_30 | ||
path: url.pathname + url.search, | ||
port: url.port, | ||
}; | ||
var req = http.request(options, function (res) { | ||
var data = []; | ||
var dataLength = 0; | ||
res.on("data", function (chunk) { | ||
data.push(chunk); | ||
// Buffer.concat will be slightly faster if we keep track of the length | ||
dataLength += chunk.length; | ||
}); | ||
res.on("end", function () { | ||
if (request.abortSignal) { | ||
request.abortSignal.onabort = null; | ||
"X-Requested-With": "XMLHttpRequest" }, httpRequest.headers), | ||
method: httpRequest.method, | ||
timeout: httpRequest.timeout, | ||
}, function (error, response, body) { | ||
if (httpRequest.abortSignal) { | ||
httpRequest.abortSignal.onabort = null; | ||
} | ||
if (error) { | ||
if (error.code === "ETIMEDOUT") { | ||
_this.logger.log(LogLevel.Warning, "Timeout from HTTP request."); | ||
reject(new TimeoutError()); | ||
} | ||
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) { | ||
var resp = void 0; | ||
if (request.responseType === "arraybuffer") { | ||
resp = Buffer.concat(data, dataLength); | ||
resolve(new HttpResponse(res.statusCode, res.statusMessage || "", resp)); | ||
} | ||
else { | ||
resp = Buffer.concat(data, dataLength).toString(); | ||
resolve(new HttpResponse(res.statusCode, res.statusMessage || "", resp)); | ||
} | ||
} | ||
else { | ||
reject(new HttpError(res.statusMessage || "", res.statusCode || 0)); | ||
} | ||
}); | ||
_this.logger.log(LogLevel.Warning, "Error from HTTP request. " + error); | ||
reject(error); | ||
return; | ||
} | ||
if (response.statusCode >= 200 && response.statusCode < 300) { | ||
resolve(new HttpResponse(response.statusCode, response.statusMessage || "", body)); | ||
} | ||
else { | ||
reject(new HttpError(response.statusMessage || "", response.statusCode || 0)); | ||
} | ||
}); | ||
if (request.abortSignal) { | ||
request.abortSignal.onabort = function () { | ||
req.abort(); | ||
if (httpRequest.abortSignal) { | ||
httpRequest.abortSignal.onabort = function () { | ||
currentRequest.abort(); | ||
reject(new AbortError()); | ||
}; | ||
} | ||
if (request.timeout) { | ||
req.setTimeout(request.timeout, function () { | ||
_this.logger.log(LogLevel.Warning, "Timeout from HTTP request."); | ||
reject(new TimeoutError()); | ||
}); | ||
} | ||
req.on("error", function (e) { | ||
_this.logger.log(LogLevel.Warning, "Error from HTTP request. " + e); | ||
reject(e); | ||
}); | ||
if (isArrayBuffer(request.content)) { | ||
req.write(Buffer.from(request.content)); | ||
} | ||
else { | ||
req.write(request.content || ""); | ||
} | ||
req.end(); | ||
}); | ||
}; | ||
NodeHttpClient.prototype.getCookieString = function (url) { | ||
return this.cookieJar.getCookieString(url); | ||
}; | ||
return NodeHttpClient; | ||
@@ -104,0 +88,0 @@ }(HttpClient)); |
@@ -5,3 +5,3 @@ export interface EventSourceConstructor { | ||
export interface WebSocketConstructor { | ||
new (url: string, protocols?: string | string[]): WebSocket; | ||
new (url: string, protocols?: string | string[], options?: any): WebSocket; | ||
readonly CLOSED: number; | ||
@@ -8,0 +8,0 @@ readonly CLOSING: number; |
@@ -62,3 +62,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
Arg.isIn(transferFormat, TransferFormat, "transferFormat"); | ||
this.logger.log(LogLevel.Trace, "(SSE transport) Connecting"); | ||
this.logger.log(LogLevel.Trace, "(SSE transport) Connecting."); | ||
// set url before accessTokenFactory because this.url is only for send and we set the auth header instead of the query string for send | ||
@@ -80,3 +80,11 @@ this.url = url; | ||
} | ||
var eventSource = new _this.eventSourceConstructor(url, { withCredentials: true }); | ||
var eventSource; | ||
if (typeof window !== "undefined") { | ||
eventSource = new _this.eventSourceConstructor(url, { withCredentials: true }); | ||
} | ||
else { | ||
// Non-browser passes cookies via the dictionary | ||
var cookies = _this.httpClient.getCookieString(url); | ||
eventSource = new _this.eventSourceConstructor(url, { withCredentials: true, headers: { Cookie: cookies } }); | ||
} | ||
try { | ||
@@ -83,0 +91,0 @@ eventSource.onmessage = function (e) { |
@@ -70,3 +70,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
if (includeContent) { | ||
detail += ". Content: '" + data + "'."; | ||
detail += ". Content: '" + data + "'"; | ||
} | ||
@@ -73,0 +73,0 @@ } |
@@ -0,1 +1,2 @@ | ||
import { HttpClient } from "./HttpClient"; | ||
import { ILogger } from "./ILogger"; | ||
@@ -10,6 +11,7 @@ import { ITransport, TransferFormat } from "./ITransport"; | ||
private readonly webSocketConstructor; | ||
private readonly httpClient; | ||
private webSocket?; | ||
onreceive: ((data: string | ArrayBuffer) => void) | null; | ||
onclose: ((error?: Error) => void) | null; | ||
constructor(accessTokenFactory: (() => string | Promise<string>) | undefined, logger: ILogger, logMessageContent: boolean, webSocketConstructor: WebSocketConstructor); | ||
constructor(httpClient: HttpClient, accessTokenFactory: (() => string | Promise<string>) | undefined, logger: ILogger, logMessageContent: boolean, webSocketConstructor: WebSocketConstructor); | ||
connect(url: string, transferFormat: TransferFormat): Promise<void>; | ||
@@ -16,0 +18,0 @@ send(data: any): Promise<void>; |
@@ -43,3 +43,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
var WebSocketTransport = /** @class */ (function () { | ||
function WebSocketTransport(accessTokenFactory, logger, logMessageContent, webSocketConstructor) { | ||
function WebSocketTransport(httpClient, accessTokenFactory, logger, logMessageContent, webSocketConstructor) { | ||
this.logger = logger; | ||
@@ -49,2 +49,3 @@ this.accessTokenFactory = accessTokenFactory; | ||
this.webSocketConstructor = webSocketConstructor; | ||
this.httpClient = httpClient; | ||
this.onreceive = null; | ||
@@ -63,3 +64,3 @@ this.onclose = null; | ||
Arg.isIn(transferFormat, TransferFormat, "transferFormat"); | ||
this.logger.log(LogLevel.Trace, "(WebSockets transport) Connecting"); | ||
this.logger.log(LogLevel.Trace, "(WebSockets transport) Connecting."); | ||
if (!this.accessTokenFactory) return [3 /*break*/, 2]; | ||
@@ -75,3 +76,16 @@ return [4 /*yield*/, this.accessTokenFactory()]; | ||
url = url.replace(/^http/, "ws"); | ||
var webSocket = new _this.webSocketConstructor(url); | ||
var webSocket; | ||
var cookies = _this.httpClient.getCookieString(url); | ||
if (typeof window === "undefined" && cookies) { | ||
// Only pass cookies when in non-browser environments | ||
webSocket = new _this.webSocketConstructor(url, undefined, { | ||
headers: { | ||
Cookie: "" + cookies, | ||
}, | ||
}); | ||
} | ||
if (!webSocket) { | ||
// Chrome is not happy with passing 'undefined' as protocol | ||
webSocket = new _this.webSocketConstructor(url); | ||
} | ||
if (transferFormat === TransferFormat.Binary) { | ||
@@ -82,3 +96,3 @@ webSocket.binaryType = "arraybuffer"; | ||
webSocket.onopen = function (_event) { | ||
_this.logger.log(LogLevel.Information, "WebSocket connected to " + url); | ||
_this.logger.log(LogLevel.Information, "WebSocket connected to " + url + "."); | ||
_this.webSocket = webSocket; | ||
@@ -134,3 +148,3 @@ resolve(); | ||
if (event && (event.wasClean === false || event.code !== 1000)) { | ||
this.onclose(new Error("Websocket closed with status code: " + event.code + " (" + event.reason + ")")); | ||
this.onclose(new Error("WebSocket closed with status code: " + event.code + " (" + event.reason + ").")); | ||
} | ||
@@ -137,0 +151,0 @@ else { |
@@ -74,3 +74,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
xhr.onerror = function () { | ||
_this.logger.log(LogLevel.Warning, "Error from HTTP request. " + xhr.status + ": " + xhr.statusText); | ||
_this.logger.log(LogLevel.Warning, "Error from HTTP request. " + xhr.status + ": " + xhr.statusText + "."); | ||
reject(new HttpError(xhr.statusText, xhr.status)); | ||
@@ -77,0 +77,0 @@ }; |
{ | ||
"name": "@aspnet/signalr", | ||
"version": "1.1.0-preview3-35497", | ||
"version": "1.1.0", | ||
"description": "ASP.NET Core SignalR Client", | ||
@@ -41,8 +41,10 @@ "main": "./dist/cjs/index.js", | ||
"@types/node": "^10.9.4", | ||
"@types/eventsource": "^1.0.2" | ||
"@types/eventsource": "^1.0.2", | ||
"@types/request": "^2.47.1" | ||
}, | ||
"dependencies": { | ||
"ws": "^6.0.0", | ||
"eventsource": "^1.0.7" | ||
"eventsource": "^1.0.7", | ||
"request": "^2.88.0" | ||
} | ||
} |
@@ -19,6 +19,3 @@ JavaScript and TypeScript clients for SignalR for ASP.NET Core | ||
The following polyfills are required to use the client in Node.js applications: | ||
- `XmlHttpRequest` - always | ||
- `WebSockets` - to use the WebSockets transport | ||
- `EventSource` - to use the ServerSentEvents transport | ||
To use the client in a NodeJS application, install the package to your `node_modules` folder and use `require('@aspnet/signalr')` to load the module. The object returned by `require('@aspnet/signalr')` has the same members as the global `signalR` object (when used in a browser). | ||
@@ -25,0 +22,0 @@ ### Example (Browser) |
@@ -11,4 +11,6 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
if (typeof XMLHttpRequest === "undefined") { | ||
// tslint:disable-next-line:no-var-requires | ||
nodeHttpClientModule = require("./NodeHttpClient"); | ||
// In order to ignore the dynamic require in webpack builds we need to do this magic | ||
// @ts-ignore: TS doesn't know about these names | ||
const requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require; | ||
nodeHttpClientModule = requireFunc("./NodeHttpClient"); | ||
} | ||
@@ -49,2 +51,6 @@ | ||
} | ||
public getCookieString(url: string): string { | ||
return this.httpClient.getCookieString(url); | ||
} | ||
} |
@@ -144,2 +144,12 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
public abstract send(request: HttpRequest): Promise<HttpResponse>; | ||
/** Gets all cookies that apply to the specified URL. | ||
* | ||
* @param url The URL that the cookies are valid for. | ||
* @returns {string} A string containing all the key-value cookie pairs for the specified URL. | ||
*/ | ||
// @ts-ignore | ||
public getCookieString(url: string): string { | ||
return ""; | ||
} | ||
} |
@@ -42,6 +42,7 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
if (typeof window === "undefined" && typeof require !== "undefined") { | ||
// tslint:disable-next-line:no-var-requires | ||
WebSocketModule = require("ws"); | ||
// tslint:disable-next-line:no-var-requires | ||
EventSourceModule = require("eventsource"); | ||
// In order to ignore the dynamic require in webpack builds we need to do this magic | ||
// @ts-ignore: TS doesn't know about these names | ||
const requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require; | ||
WebSocketModule = requireFunc("ws"); | ||
EventSourceModule = requireFunc("eventsource"); | ||
} | ||
@@ -234,3 +235,3 @@ | ||
const negotiateUrl = this.resolveNegotiateUrl(url); | ||
this.logger.log(LogLevel.Debug, `Sending negotiation request: ${negotiateUrl}`); | ||
this.logger.log(LogLevel.Debug, `Sending negotiation request: ${negotiateUrl}.`); | ||
try { | ||
@@ -304,3 +305,3 @@ const response = await this.httpClient.post(negotiateUrl, { | ||
} | ||
return new WebSocketTransport(this.accessTokenFactory, this.logger, this.options.logMessageContent || false, this.options.WebSocket); | ||
return new WebSocketTransport(this.httpClient, this.accessTokenFactory, this.logger, this.options.logMessageContent || false, this.options.WebSocket); | ||
case HttpTransportType.ServerSentEvents: | ||
@@ -330,3 +331,3 @@ if (!this.options.EventSource) { | ||
} else { | ||
this.logger.log(LogLevel.Debug, `Selecting transport '${HttpTransportType[transport]}'`); | ||
this.logger.log(LogLevel.Debug, `Selecting transport '${HttpTransportType[transport]}'.`); | ||
return transport; | ||
@@ -333,0 +334,0 @@ } |
@@ -376,3 +376,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
default: | ||
this.logger.log(LogLevel.Warning, "Invalid message type: " + message.type); | ||
this.logger.log(LogLevel.Warning, `Invalid message type: ${message.type}.`); | ||
break; | ||
@@ -379,0 +379,0 @@ } |
@@ -53,3 +53,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
this.logger.log(LogLevel.Trace, "(LongPolling transport) Connecting"); | ||
this.logger.log(LogLevel.Trace, "(LongPolling transport) Connecting."); | ||
@@ -78,6 +78,6 @@ // Allow binary format on Node and Browsers that support binary content (indicated by the presence of responseType property) | ||
const pollUrl = `${url}&_=${Date.now()}`; | ||
this.logger.log(LogLevel.Trace, `(LongPolling transport) polling: ${pollUrl}`); | ||
this.logger.log(LogLevel.Trace, `(LongPolling transport) polling: ${pollUrl}.`); | ||
const response = await this.httpClient.get(pollUrl, pollOptions); | ||
if (response.statusCode !== 200) { | ||
this.logger.log(LogLevel.Error, `(LongPolling transport) Unexpected response code: ${response.statusCode}`); | ||
this.logger.log(LogLevel.Error, `(LongPolling transport) Unexpected response code: ${response.statusCode}.`); | ||
@@ -127,11 +127,11 @@ // Mark running as false so that the poll immediately ends and runs the close logic | ||
const pollUrl = `${url}&_=${Date.now()}`; | ||
this.logger.log(LogLevel.Trace, `(LongPolling transport) polling: ${pollUrl}`); | ||
this.logger.log(LogLevel.Trace, `(LongPolling transport) polling: ${pollUrl}.`); | ||
const response = await this.httpClient.get(pollUrl, pollOptions); | ||
if (response.statusCode === 204) { | ||
this.logger.log(LogLevel.Information, "(LongPolling transport) Poll terminated by server"); | ||
this.logger.log(LogLevel.Information, "(LongPolling transport) Poll terminated by server."); | ||
this.running = false; | ||
} else if (response.statusCode !== 200) { | ||
this.logger.log(LogLevel.Error, `(LongPolling transport) Unexpected response code: ${response.statusCode}`); | ||
this.logger.log(LogLevel.Error, `(LongPolling transport) Unexpected response code: ${response.statusCode}.`); | ||
@@ -144,3 +144,3 @@ // Unexpected status code | ||
if (response.content) { | ||
this.logger.log(LogLevel.Trace, `(LongPolling transport) data received. ${getDataDetail(response.content, this.logMessageContent)}`); | ||
this.logger.log(LogLevel.Trace, `(LongPolling transport) data received. ${getDataDetail(response.content, this.logMessageContent)}.`); | ||
if (this.onreceive) { | ||
@@ -147,0 +147,0 @@ this.onreceive(response.content); |
// 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 * as http from "http"; | ||
import { URL } from "url"; | ||
import * as Request from "request"; | ||
@@ -14,2 +13,4 @@ import { AbortError, HttpError, TimeoutError } from "./Errors"; | ||
private readonly logger: ILogger; | ||
private readonly request: Request.RequestAPI<Request.Request, Request.CoreOptions, Request.RequiredUriUrl>; | ||
private readonly cookieJar: Request.CookieJar; | ||
@@ -19,76 +20,62 @@ public constructor(logger: ILogger) { | ||
this.logger = logger; | ||
this.cookieJar = Request.jar(); | ||
this.request = Request.defaults({ jar: this.cookieJar }); | ||
} | ||
public send(request: HttpRequest): Promise<HttpResponse> { | ||
public send(httpRequest: HttpRequest): Promise<HttpResponse> { | ||
return new Promise<HttpResponse>((resolve, reject) => { | ||
const url = new URL(request.url!); | ||
const options: http.RequestOptions = { | ||
let requestBody: Buffer | string; | ||
if (isArrayBuffer(httpRequest.content)) { | ||
requestBody = Buffer.from(httpRequest.content); | ||
} else { | ||
requestBody = httpRequest.content || ""; | ||
} | ||
const currentRequest = this.request(httpRequest.url!, { | ||
body: requestBody, | ||
// If binary is expected 'null' should be used, otherwise for text 'utf8' | ||
encoding: httpRequest.responseType === "arraybuffer" ? null : "utf8", | ||
headers: { | ||
// Tell auth middleware to 401 instead of redirecting | ||
"X-Requested-With": "XMLHttpRequest", | ||
...request.headers, | ||
...httpRequest.headers, | ||
}, | ||
hostname: url.hostname, | ||
method: request.method, | ||
// /abc/xyz + ?id=12ssa_30 | ||
path: url.pathname + url.search, | ||
port: url.port, | ||
}; | ||
method: httpRequest.method, | ||
timeout: httpRequest.timeout, | ||
}, | ||
(error, response, body) => { | ||
if (httpRequest.abortSignal) { | ||
httpRequest.abortSignal.onabort = null; | ||
} | ||
const req = http.request(options, (res: http.IncomingMessage) => { | ||
const data: Buffer[] = []; | ||
let dataLength = 0; | ||
res.on("data", (chunk: any) => { | ||
data.push(chunk); | ||
// Buffer.concat will be slightly faster if we keep track of the length | ||
dataLength += chunk.length; | ||
}); | ||
res.on("end", () => { | ||
if (request.abortSignal) { | ||
request.abortSignal.onabort = null; | ||
if (error) { | ||
if (error.code === "ETIMEDOUT") { | ||
this.logger.log(LogLevel.Warning, `Timeout from HTTP request.`); | ||
reject(new TimeoutError()); | ||
} | ||
this.logger.log(LogLevel.Warning, `Error from HTTP request. ${error}`); | ||
reject(error); | ||
return; | ||
} | ||
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) { | ||
let resp: string | ArrayBuffer; | ||
if (request.responseType === "arraybuffer") { | ||
resp = Buffer.concat(data, dataLength); | ||
resolve(new HttpResponse(res.statusCode, res.statusMessage || "", resp)); | ||
} else { | ||
resp = Buffer.concat(data, dataLength).toString(); | ||
resolve(new HttpResponse(res.statusCode, res.statusMessage || "", resp)); | ||
} | ||
} else { | ||
reject(new HttpError(res.statusMessage || "", res.statusCode || 0)); | ||
} | ||
}); | ||
if (response.statusCode >= 200 && response.statusCode < 300) { | ||
resolve(new HttpResponse(response.statusCode, response.statusMessage || "", body)); | ||
} else { | ||
reject(new HttpError(response.statusMessage || "", response.statusCode || 0)); | ||
} | ||
}); | ||
if (request.abortSignal) { | ||
request.abortSignal.onabort = () => { | ||
req.abort(); | ||
if (httpRequest.abortSignal) { | ||
httpRequest.abortSignal.onabort = () => { | ||
currentRequest.abort(); | ||
reject(new AbortError()); | ||
}; | ||
} | ||
if (request.timeout) { | ||
req.setTimeout(request.timeout, () => { | ||
this.logger.log(LogLevel.Warning, `Timeout from HTTP request.`); | ||
reject(new TimeoutError()); | ||
}); | ||
} | ||
req.on("error", (e) => { | ||
this.logger.log(LogLevel.Warning, `Error from HTTP request. ${e}`); | ||
reject(e); | ||
}); | ||
if (isArrayBuffer(request.content)) { | ||
req.write(Buffer.from(request.content)); | ||
} else { | ||
req.write(request.content || ""); | ||
} | ||
req.end(); | ||
}); | ||
} | ||
public getCookieString(url: string): string { | ||
return this.cookieJar.getCookieString(url); | ||
} | ||
} |
@@ -11,3 +11,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
export interface WebSocketConstructor { | ||
new(url: string, protocols?: string | string[]): WebSocket; | ||
new(url: string, protocols?: string | string[], options?: any): WebSocket; | ||
readonly CLOSED: number; | ||
@@ -14,0 +14,0 @@ readonly CLOSING: number; |
@@ -40,3 +40,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
this.logger.log(LogLevel.Trace, "(SSE transport) Connecting"); | ||
this.logger.log(LogLevel.Trace, "(SSE transport) Connecting."); | ||
@@ -60,3 +60,10 @@ // set url before accessTokenFactory because this.url is only for send and we set the auth header instead of the query string for send | ||
const eventSource = new this.eventSourceConstructor(url, { withCredentials: true }); | ||
let eventSource: EventSource; | ||
if (typeof window !== "undefined") { | ||
eventSource = new this.eventSourceConstructor(url, { withCredentials: true }); | ||
} else { | ||
// Non-browser passes cookies via the dictionary | ||
const cookies = this.httpClient.getCookieString(url); | ||
eventSource = new this.eventSourceConstructor(url, { withCredentials: true, headers: { Cookie: cookies } } as EventSourceInit); | ||
} | ||
@@ -63,0 +70,0 @@ try { |
@@ -36,3 +36,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
if (includeContent) { | ||
detail += `. Content: '${data}'.`; | ||
detail += `. Content: '${data}'`; | ||
} | ||
@@ -39,0 +39,0 @@ } |
// 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 { HttpClient } from "./HttpClient"; | ||
import { ILogger, LogLevel } from "./ILogger"; | ||
@@ -15,2 +16,3 @@ import { ITransport, TransferFormat } from "./ITransport"; | ||
private readonly webSocketConstructor: WebSocketConstructor; | ||
private readonly httpClient: HttpClient; | ||
private webSocket?: WebSocket; | ||
@@ -21,3 +23,3 @@ | ||
constructor(accessTokenFactory: (() => string | Promise<string>) | undefined, logger: ILogger, | ||
constructor(httpClient: HttpClient, accessTokenFactory: (() => string | Promise<string>) | undefined, logger: ILogger, | ||
logMessageContent: boolean, webSocketConstructor: WebSocketConstructor) { | ||
@@ -28,2 +30,3 @@ this.logger = logger; | ||
this.webSocketConstructor = webSocketConstructor; | ||
this.httpClient = httpClient; | ||
@@ -39,3 +42,3 @@ this.onreceive = null; | ||
this.logger.log(LogLevel.Trace, "(WebSockets transport) Connecting"); | ||
this.logger.log(LogLevel.Trace, "(WebSockets transport) Connecting."); | ||
@@ -51,3 +54,19 @@ if (this.accessTokenFactory) { | ||
url = url.replace(/^http/, "ws"); | ||
const webSocket = new this.webSocketConstructor(url); | ||
let webSocket: WebSocket | undefined; | ||
const cookies = this.httpClient.getCookieString(url); | ||
if (typeof window === "undefined" && cookies) { | ||
// Only pass cookies when in non-browser environments | ||
webSocket = new this.webSocketConstructor(url, undefined, { | ||
headers: { | ||
Cookie: `${cookies}`, | ||
}, | ||
}); | ||
} | ||
if (!webSocket) { | ||
// Chrome is not happy with passing 'undefined' as protocol | ||
webSocket = new this.webSocketConstructor(url); | ||
} | ||
if (transferFormat === TransferFormat.Binary) { | ||
@@ -59,3 +78,3 @@ webSocket.binaryType = "arraybuffer"; | ||
webSocket.onopen = (_event: Event) => { | ||
this.logger.log(LogLevel.Information, `WebSocket connected to ${url}`); | ||
this.logger.log(LogLevel.Information, `WebSocket connected to ${url}.`); | ||
this.webSocket = webSocket; | ||
@@ -117,3 +136,3 @@ resolve(); | ||
if (event && (event.wasClean === false || event.code !== 1000)) { | ||
this.onclose(new Error(`Websocket closed with status code: ${event.code} (${event.reason})`)); | ||
this.onclose(new Error(`WebSocket closed with status code: ${event.code} (${event.reason}).`)); | ||
} else { | ||
@@ -120,0 +139,0 @@ this.onclose(); |
@@ -75,3 +75,3 @@ // Copyright (c) .NET Foundation. All rights reserved. | ||
xhr.onerror = () => { | ||
this.logger.log(LogLevel.Warning, `Error from HTTP request. ${xhr.status}: ${xhr.statusText}`); | ||
this.logger.log(LogLevel.Warning, `Error from HTTP request. ${xhr.status}: ${xhr.statusText}.`); | ||
reject(new HttpError(xhr.statusText, xhr.status)); | ||
@@ -78,0 +78,0 @@ }; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1371953
12601
1
6
3
4
52
10
+ Addedrequest@^2.88.0
+ Addedajv@6.12.6(transitive)
+ Addedasn1@0.2.6(transitive)
+ Addedassert-plus@1.0.0(transitive)
+ Addedasynckit@0.4.0(transitive)
+ Addedaws-sign2@0.7.0(transitive)
+ Addedaws4@1.13.2(transitive)
+ Addedbcrypt-pbkdf@1.0.2(transitive)
+ Addedcaseless@0.12.0(transitive)
+ Addedcombined-stream@1.0.8(transitive)
+ Addedcore-util-is@1.0.2(transitive)
+ Addeddashdash@1.14.1(transitive)
+ Addeddelayed-stream@1.0.0(transitive)
+ Addedecc-jsbn@0.1.2(transitive)
+ Addedextend@3.0.2(transitive)
+ Addedextsprintf@1.3.0(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedforever-agent@0.6.1(transitive)
+ Addedform-data@2.3.3(transitive)
+ Addedgetpass@0.1.7(transitive)
+ Addedhar-schema@2.0.0(transitive)
+ Addedhar-validator@5.1.5(transitive)
+ Addedhttp-signature@1.2.0(transitive)
+ Addedis-typedarray@1.0.0(transitive)
+ Addedisstream@0.1.2(transitive)
+ Addedjsbn@0.1.1(transitive)
+ Addedjson-schema@0.4.0(transitive)
+ Addedjson-schema-traverse@0.4.1(transitive)
+ Addedjson-stringify-safe@5.0.1(transitive)
+ Addedjsprim@1.4.2(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addedoauth-sign@0.9.0(transitive)
+ Addedperformance-now@2.1.0(transitive)
+ Addedpsl@1.15.0(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addedqs@6.5.3(transitive)
+ Addedrequest@2.88.2(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsshpk@1.18.0(transitive)
+ Addedtough-cookie@2.5.0(transitive)
+ Addedtunnel-agent@0.6.0(transitive)
+ Addedtweetnacl@0.14.5(transitive)
+ Addeduri-js@4.4.1(transitive)
+ Addeduuid@3.4.0(transitive)
+ Addedverror@1.10.0(transitive)