ServerSentEventsTransport.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. "use strict";
  2. // Licensed to the .NET Foundation under one or more agreements.
  3. // The .NET Foundation licenses this file to you under the MIT license.
  4. Object.defineProperty(exports, "__esModule", { value: true });
  5. exports.ServerSentEventsTransport = void 0;
  6. const ILogger_1 = require("./ILogger");
  7. const ITransport_1 = require("./ITransport");
  8. const Utils_1 = require("./Utils");
  9. /** @private */
  10. class ServerSentEventsTransport {
  11. constructor(httpClient, accessToken, logger, options) {
  12. this._httpClient = httpClient;
  13. this._accessToken = accessToken;
  14. this._logger = logger;
  15. this._options = options;
  16. this.onreceive = null;
  17. this.onclose = null;
  18. }
  19. async connect(url, transferFormat) {
  20. Utils_1.Arg.isRequired(url, "url");
  21. Utils_1.Arg.isRequired(transferFormat, "transferFormat");
  22. Utils_1.Arg.isIn(transferFormat, ITransport_1.TransferFormat, "transferFormat");
  23. this._logger.log(ILogger_1.LogLevel.Trace, "(SSE transport) Connecting.");
  24. // set url before accessTokenFactory because this._url is only for send and we set the auth header instead of the query string for send
  25. this._url = url;
  26. if (this._accessToken) {
  27. url += (url.indexOf("?") < 0 ? "?" : "&") + `access_token=${encodeURIComponent(this._accessToken)}`;
  28. }
  29. return new Promise((resolve, reject) => {
  30. let opened = false;
  31. if (transferFormat !== ITransport_1.TransferFormat.Text) {
  32. reject(new Error("The Server-Sent Events transport only supports the 'Text' transfer format"));
  33. return;
  34. }
  35. let eventSource;
  36. if (Utils_1.Platform.isBrowser || Utils_1.Platform.isWebWorker) {
  37. eventSource = new this._options.EventSource(url, { withCredentials: this._options.withCredentials });
  38. }
  39. else {
  40. // Non-browser passes cookies via the dictionary
  41. const cookies = this._httpClient.getCookieString(url);
  42. const headers = {};
  43. headers.Cookie = cookies;
  44. const [name, value] = Utils_1.getUserAgentHeader();
  45. headers[name] = value;
  46. eventSource = new this._options.EventSource(url, { withCredentials: this._options.withCredentials, headers: { ...headers, ...this._options.headers } });
  47. }
  48. try {
  49. eventSource.onmessage = (e) => {
  50. if (this.onreceive) {
  51. try {
  52. this._logger.log(ILogger_1.LogLevel.Trace, `(SSE transport) data received. ${Utils_1.getDataDetail(e.data, this._options.logMessageContent)}.`);
  53. this.onreceive(e.data);
  54. }
  55. catch (error) {
  56. this._close(error);
  57. return;
  58. }
  59. }
  60. };
  61. // @ts-ignore: not using event on purpose
  62. eventSource.onerror = (e) => {
  63. // EventSource doesn't give any useful information about server side closes.
  64. if (opened) {
  65. this._close();
  66. }
  67. else {
  68. reject(new Error("EventSource failed to connect. The connection could not be found on the server,"
  69. + " either the connection ID is not present on the server, or a proxy is refusing/buffering the connection."
  70. + " If you have multiple servers check that sticky sessions are enabled."));
  71. }
  72. };
  73. eventSource.onopen = () => {
  74. this._logger.log(ILogger_1.LogLevel.Information, `SSE connected to ${this._url}`);
  75. this._eventSource = eventSource;
  76. opened = true;
  77. resolve();
  78. };
  79. }
  80. catch (e) {
  81. reject(e);
  82. return;
  83. }
  84. });
  85. }
  86. async send(data) {
  87. if (!this._eventSource) {
  88. return Promise.reject(new Error("Cannot send until the transport is connected"));
  89. }
  90. return Utils_1.sendMessage(this._logger, "SSE", this._httpClient, this._url, data, this._options);
  91. }
  92. stop() {
  93. this._close();
  94. return Promise.resolve();
  95. }
  96. _close(e) {
  97. if (this._eventSource) {
  98. this._eventSource.close();
  99. this._eventSource = undefined;
  100. if (this.onclose) {
  101. this.onclose(e);
  102. }
  103. }
  104. }
  105. }
  106. exports.ServerSentEventsTransport = ServerSentEventsTransport;
  107. //# sourceMappingURL=ServerSentEventsTransport.js.map