@stomp/stompjs 6.1.2 → 7.0.0-beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/stomp.umd.js +1724 -2023
- package/bundles/stomp.umd.js.map +1 -1
- package/bundles/stomp.umd.min.js +1 -2
- package/esm6/augment-websocket.d.ts +1 -1
- package/esm6/augment-websocket.js +4 -3
- package/esm6/augment-websocket.js.map +1 -1
- package/esm6/client.d.ts +35 -19
- package/esm6/client.js +176 -132
- package/esm6/client.js.map +1 -1
- package/esm6/compatibility/compat-client.d.ts +29 -23
- package/esm6/compatibility/compat-client.js +2 -2
- package/esm6/compatibility/compat-client.js.map +1 -1
- package/esm6/compatibility/heartbeat-info.d.ts +5 -3
- package/esm6/compatibility/stomp.d.ts +1 -1
- package/esm6/compatibility/stomp.js +2 -2
- package/esm6/compatibility/stomp.js.map +1 -1
- package/esm6/frame-impl.d.ts +5 -5
- package/esm6/frame-impl.js +3 -2
- package/esm6/frame-impl.js.map +1 -1
- package/esm6/i-frame.d.ts +1 -1
- package/esm6/i-frame.js +1 -0
- package/esm6/i-message.d.ts +2 -2
- package/esm6/i-message.js +1 -0
- package/esm6/i-transaction.js +1 -0
- package/esm6/index.d.ts +13 -13
- package/esm6/index.js +13 -10
- package/esm6/index.js.map +1 -1
- package/esm6/parser.d.ts +1 -1
- package/esm6/parser.js +10 -2
- package/esm6/parser.js.map +1 -1
- package/esm6/stomp-config.d.ts +3 -3
- package/esm6/stomp-handler.d.ts +10 -13
- package/esm6/stomp-handler.js +35 -17
- package/esm6/stomp-handler.js.map +1 -1
- package/esm6/stomp-subscription.d.ts +2 -2
- package/esm6/stomp-subscription.js +1 -7
- package/esm6/stomp-subscription.js.map +1 -1
- package/esm6/types.d.ts +31 -5
- package/esm6/types.js +2 -2
- package/esm6/types.js.map +1 -1
- package/esm6/versions.js +2 -2
- package/index.d.ts +1 -1
- package/package.json +28 -25
- package/src/augment-websocket.ts +5 -4
- package/src/client.ts +81 -35
- package/src/compatibility/compat-client.ts +4 -4
- package/src/compatibility/heartbeat-info.ts +1 -1
- package/src/compatibility/stomp.ts +3 -3
- package/src/frame-impl.ts +14 -10
- package/src/i-frame.ts +1 -1
- package/src/i-message.ts +2 -2
- package/src/index.ts +13 -13
- package/src/parser.ts +18 -6
- package/src/stomp-config.ts +3 -3
- package/src/stomp-handler.ts +47 -31
- package/src/stomp-subscription.ts +4 -4
- package/src/types.ts +32 -5
- package/src/versions.ts +2 -2
- package/bundles/stomp.umd.min.js.map +0 -1
package/bundles/stomp.umd.js
CHANGED
|
@@ -1,2170 +1,1871 @@
|
|
|
1
|
-
(function
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
else if(typeof exports === 'object')
|
|
7
|
-
exports["StompJs"] = factory();
|
|
8
|
-
else
|
|
9
|
-
root["StompJs"] = factory();
|
|
10
|
-
})(typeof self !== 'undefined' ? self : this, function() {
|
|
11
|
-
return /******/ (function(modules) { // webpackBootstrap
|
|
12
|
-
/******/ // The module cache
|
|
13
|
-
/******/ var installedModules = {};
|
|
14
|
-
/******/
|
|
15
|
-
/******/ // The require function
|
|
16
|
-
/******/ function __webpack_require__(moduleId) {
|
|
17
|
-
/******/
|
|
18
|
-
/******/ // Check if module is in cache
|
|
19
|
-
/******/ if(installedModules[moduleId]) {
|
|
20
|
-
/******/ return installedModules[moduleId].exports;
|
|
21
|
-
/******/ }
|
|
22
|
-
/******/ // Create a new module (and put it into the cache)
|
|
23
|
-
/******/ var module = installedModules[moduleId] = {
|
|
24
|
-
/******/ i: moduleId,
|
|
25
|
-
/******/ l: false,
|
|
26
|
-
/******/ exports: {}
|
|
27
|
-
/******/ };
|
|
28
|
-
/******/
|
|
29
|
-
/******/ // Execute the module function
|
|
30
|
-
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
31
|
-
/******/
|
|
32
|
-
/******/ // Flag the module as loaded
|
|
33
|
-
/******/ module.l = true;
|
|
34
|
-
/******/
|
|
35
|
-
/******/ // Return the exports of the module
|
|
36
|
-
/******/ return module.exports;
|
|
37
|
-
/******/ }
|
|
38
|
-
/******/
|
|
39
|
-
/******/
|
|
40
|
-
/******/ // expose the modules object (__webpack_modules__)
|
|
41
|
-
/******/ __webpack_require__.m = modules;
|
|
42
|
-
/******/
|
|
43
|
-
/******/ // expose the module cache
|
|
44
|
-
/******/ __webpack_require__.c = installedModules;
|
|
45
|
-
/******/
|
|
46
|
-
/******/ // define getter function for harmony exports
|
|
47
|
-
/******/ __webpack_require__.d = function(exports, name, getter) {
|
|
48
|
-
/******/ if(!__webpack_require__.o(exports, name)) {
|
|
49
|
-
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
|
50
|
-
/******/ }
|
|
51
|
-
/******/ };
|
|
52
|
-
/******/
|
|
53
|
-
/******/ // define __esModule on exports
|
|
54
|
-
/******/ __webpack_require__.r = function(exports) {
|
|
55
|
-
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
56
|
-
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
57
|
-
/******/ }
|
|
58
|
-
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
59
|
-
/******/ };
|
|
60
|
-
/******/
|
|
61
|
-
/******/ // create a fake namespace object
|
|
62
|
-
/******/ // mode & 1: value is a module id, require it
|
|
63
|
-
/******/ // mode & 2: merge all properties of value into the ns
|
|
64
|
-
/******/ // mode & 4: return value when already ns object
|
|
65
|
-
/******/ // mode & 8|1: behave like require
|
|
66
|
-
/******/ __webpack_require__.t = function(value, mode) {
|
|
67
|
-
/******/ if(mode & 1) value = __webpack_require__(value);
|
|
68
|
-
/******/ if(mode & 8) return value;
|
|
69
|
-
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
|
70
|
-
/******/ var ns = Object.create(null);
|
|
71
|
-
/******/ __webpack_require__.r(ns);
|
|
72
|
-
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
|
73
|
-
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
|
74
|
-
/******/ return ns;
|
|
75
|
-
/******/ };
|
|
76
|
-
/******/
|
|
77
|
-
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
78
|
-
/******/ __webpack_require__.n = function(module) {
|
|
79
|
-
/******/ var getter = module && module.__esModule ?
|
|
80
|
-
/******/ function getDefault() { return module['default']; } :
|
|
81
|
-
/******/ function getModuleExports() { return module; };
|
|
82
|
-
/******/ __webpack_require__.d(getter, 'a', getter);
|
|
83
|
-
/******/ return getter;
|
|
84
|
-
/******/ };
|
|
85
|
-
/******/
|
|
86
|
-
/******/ // Object.prototype.hasOwnProperty.call
|
|
87
|
-
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
88
|
-
/******/
|
|
89
|
-
/******/ // __webpack_public_path__
|
|
90
|
-
/******/ __webpack_require__.p = "";
|
|
91
|
-
/******/
|
|
92
|
-
/******/
|
|
93
|
-
/******/ // Load entry module and return exports
|
|
94
|
-
/******/ return __webpack_require__(__webpack_require__.s = 0);
|
|
95
|
-
/******/ })
|
|
96
|
-
/************************************************************************/
|
|
97
|
-
/******/ ({
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.StompJs = {}));
|
|
5
|
+
})(this, (function (exports) { 'use strict';
|
|
98
6
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
*/
|
|
112
|
-
function augmentWebsocket(webSocket, debug) {
|
|
113
|
-
webSocket.terminate = function () {
|
|
114
|
-
const noOp = () => { };
|
|
115
|
-
// set all callbacks to no op
|
|
116
|
-
this.onerror = noOp;
|
|
117
|
-
this.onmessage = noOp;
|
|
118
|
-
this.onopen = noOp;
|
|
119
|
-
const ts = new Date();
|
|
120
|
-
const origOnClose = this.onclose;
|
|
121
|
-
// Track delay in actual closure of the socket
|
|
122
|
-
this.onclose = closeEvent => {
|
|
123
|
-
const delay = new Date().getTime() - ts.getTime();
|
|
124
|
-
debug(`Discarded socket closed after ${delay}ms, with code/reason: ${closeEvent.code}/${closeEvent.reason}`);
|
|
125
|
-
};
|
|
126
|
-
this.close();
|
|
127
|
-
origOnClose.call(this, {
|
|
128
|
-
code: 4001,
|
|
129
|
-
reason: 'Heartbeat failure, discarding the socket',
|
|
130
|
-
wasClean: false,
|
|
131
|
-
});
|
|
7
|
+
/**
|
|
8
|
+
* Some byte values, used as per STOMP specifications.
|
|
9
|
+
*
|
|
10
|
+
* Part of `@stomp/stompjs`.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
const BYTE = {
|
|
15
|
+
// LINEFEED byte (octet 10)
|
|
16
|
+
LF: '\x0A',
|
|
17
|
+
// NULL byte (octet 0)
|
|
18
|
+
NULL: '\x00',
|
|
132
19
|
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
/***/ }),
|
|
137
|
-
|
|
138
|
-
/***/ "./src/byte.ts":
|
|
139
|
-
/*!*********************!*\
|
|
140
|
-
!*** ./src/byte.ts ***!
|
|
141
|
-
\*********************/
|
|
142
|
-
/*! exports provided: BYTE */
|
|
143
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
144
|
-
|
|
145
|
-
"use strict";
|
|
146
|
-
__webpack_require__.r(__webpack_exports__);
|
|
147
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BYTE", function() { return BYTE; });
|
|
148
|
-
/**
|
|
149
|
-
* Some byte values, used as per STOMP specifications.
|
|
150
|
-
*
|
|
151
|
-
* Part of `@stomp/stompjs`.
|
|
152
|
-
*
|
|
153
|
-
* @internal
|
|
154
|
-
*/
|
|
155
|
-
const BYTE = {
|
|
156
|
-
// LINEFEED byte (octet 10)
|
|
157
|
-
LF: '\x0A',
|
|
158
|
-
// NULL byte (octet 0)
|
|
159
|
-
NULL: '\x00',
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
/***/ }),
|
|
164
|
-
|
|
165
|
-
/***/ "./src/client.ts":
|
|
166
|
-
/*!***********************!*\
|
|
167
|
-
!*** ./src/client.ts ***!
|
|
168
|
-
\***********************/
|
|
169
|
-
/*! exports provided: Client */
|
|
170
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
171
|
-
|
|
172
|
-
"use strict";
|
|
173
|
-
__webpack_require__.r(__webpack_exports__);
|
|
174
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Client", function() { return Client; });
|
|
175
|
-
/* harmony import */ var _stomp_handler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./stomp-handler */ "./src/stomp-handler.ts");
|
|
176
|
-
/* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./types */ "./src/types.ts");
|
|
177
|
-
/* harmony import */ var _versions__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./versions */ "./src/versions.ts");
|
|
178
|
-
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
179
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
180
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
181
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
182
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
183
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
184
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
185
|
-
});
|
|
186
|
-
};
|
|
187
|
-
|
|
188
20
|
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* STOMP Client Class.
|
|
192
|
-
*
|
|
193
|
-
* Part of `@stomp/stompjs`.
|
|
194
|
-
*/
|
|
195
|
-
class Client {
|
|
196
21
|
/**
|
|
197
|
-
*
|
|
22
|
+
* Frame class represents a STOMP frame.
|
|
23
|
+
*
|
|
24
|
+
* @internal
|
|
198
25
|
*/
|
|
199
|
-
|
|
26
|
+
class FrameImpl {
|
|
200
27
|
/**
|
|
201
|
-
*
|
|
28
|
+
* Frame constructor. `command`, `headers` and `body` are available as properties.
|
|
202
29
|
*
|
|
203
|
-
*
|
|
204
|
-
* ```javascript
|
|
205
|
-
* // Try only versions 1.0 and 1.1
|
|
206
|
-
* client.stompVersions = new Versions(['1.0', '1.1'])
|
|
207
|
-
* ```
|
|
30
|
+
* @internal
|
|
208
31
|
*/
|
|
209
|
-
|
|
32
|
+
constructor(params) {
|
|
33
|
+
const { command, headers, body, binaryBody, escapeHeaderValues, skipContentLengthHeader, } = params;
|
|
34
|
+
this.command = command;
|
|
35
|
+
this.headers = Object.assign({}, headers || {});
|
|
36
|
+
if (binaryBody) {
|
|
37
|
+
this._binaryBody = binaryBody;
|
|
38
|
+
this.isBinaryBody = true;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
this._body = body || '';
|
|
42
|
+
this.isBinaryBody = false;
|
|
43
|
+
}
|
|
44
|
+
this.escapeHeaderValues = escapeHeaderValues || false;
|
|
45
|
+
this.skipContentLengthHeader = skipContentLengthHeader || false;
|
|
46
|
+
}
|
|
210
47
|
/**
|
|
211
|
-
*
|
|
212
|
-
* Default 0, which implies wait for ever.
|
|
48
|
+
* body of the frame
|
|
213
49
|
*/
|
|
214
|
-
|
|
50
|
+
get body() {
|
|
51
|
+
if (!this._body && this.isBinaryBody) {
|
|
52
|
+
this._body = new TextDecoder().decode(this._binaryBody);
|
|
53
|
+
}
|
|
54
|
+
return this._body || '';
|
|
55
|
+
}
|
|
215
56
|
/**
|
|
216
|
-
*
|
|
57
|
+
* body as Uint8Array
|
|
217
58
|
*/
|
|
218
|
-
|
|
59
|
+
get binaryBody() {
|
|
60
|
+
if (!this._binaryBody && !this.isBinaryBody) {
|
|
61
|
+
this._binaryBody = new TextEncoder().encode(this._body);
|
|
62
|
+
}
|
|
63
|
+
// At this stage it will definitely have a valid value
|
|
64
|
+
return this._binaryBody;
|
|
65
|
+
}
|
|
219
66
|
/**
|
|
220
|
-
*
|
|
67
|
+
* deserialize a STOMP Frame from raw data.
|
|
68
|
+
*
|
|
69
|
+
* @internal
|
|
221
70
|
*/
|
|
222
|
-
|
|
71
|
+
static fromRawFrame(rawFrame, escapeHeaderValues) {
|
|
72
|
+
const headers = {};
|
|
73
|
+
const trim = (str) => str.replace(/^\s+|\s+$/g, '');
|
|
74
|
+
// In case of repeated headers, as per standards, first value need to be used
|
|
75
|
+
for (const header of rawFrame.headers.reverse()) {
|
|
76
|
+
header.indexOf(':');
|
|
77
|
+
const key = trim(header[0]);
|
|
78
|
+
let value = trim(header[1]);
|
|
79
|
+
if (escapeHeaderValues &&
|
|
80
|
+
rawFrame.command !== 'CONNECT' &&
|
|
81
|
+
rawFrame.command !== 'CONNECTED') {
|
|
82
|
+
value = FrameImpl.hdrValueUnEscape(value);
|
|
83
|
+
}
|
|
84
|
+
headers[key] = value;
|
|
85
|
+
}
|
|
86
|
+
return new FrameImpl({
|
|
87
|
+
command: rawFrame.command,
|
|
88
|
+
headers,
|
|
89
|
+
binaryBody: rawFrame.binaryBody,
|
|
90
|
+
escapeHeaderValues,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
223
93
|
/**
|
|
224
|
-
*
|
|
94
|
+
* @internal
|
|
225
95
|
*/
|
|
226
|
-
|
|
96
|
+
toString() {
|
|
97
|
+
return this.serializeCmdAndHeaders();
|
|
98
|
+
}
|
|
227
99
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
100
|
+
* serialize this Frame in a format suitable to be passed to WebSocket.
|
|
101
|
+
* If the body is string the output will be string.
|
|
102
|
+
* If the body is binary (i.e. of type Unit8Array) it will be serialized to ArrayBuffer.
|
|
231
103
|
*
|
|
232
|
-
*
|
|
233
|
-
* so it is not needed with a truly compliant STOMP/WebSocket broker.
|
|
234
|
-
* Actually setting it for such broker will cause large messages to fail.
|
|
235
|
-
*
|
|
236
|
-
* `false` by default.
|
|
237
|
-
*
|
|
238
|
-
* Binary frames are never split.
|
|
104
|
+
* @internal
|
|
239
105
|
*/
|
|
240
|
-
|
|
106
|
+
serialize() {
|
|
107
|
+
const cmdAndHeaders = this.serializeCmdAndHeaders();
|
|
108
|
+
if (this.isBinaryBody) {
|
|
109
|
+
return FrameImpl.toUnit8Array(cmdAndHeaders, this._binaryBody).buffer;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
return cmdAndHeaders + this._body + BYTE.NULL;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
serializeCmdAndHeaders() {
|
|
116
|
+
const lines = [this.command];
|
|
117
|
+
if (this.skipContentLengthHeader) {
|
|
118
|
+
delete this.headers['content-length'];
|
|
119
|
+
}
|
|
120
|
+
for (const name of Object.keys(this.headers || {})) {
|
|
121
|
+
const value = this.headers[name];
|
|
122
|
+
if (this.escapeHeaderValues &&
|
|
123
|
+
this.command !== 'CONNECT' &&
|
|
124
|
+
this.command !== 'CONNECTED') {
|
|
125
|
+
lines.push(`${name}:${FrameImpl.hdrValueEscape(`${value}`)}`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
lines.push(`${name}:${value}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (this.isBinaryBody ||
|
|
132
|
+
(!this.isBodyEmpty() && !this.skipContentLengthHeader)) {
|
|
133
|
+
lines.push(`content-length:${this.bodyLength()}`);
|
|
134
|
+
}
|
|
135
|
+
return lines.join(BYTE.LF) + BYTE.LF + BYTE.LF;
|
|
136
|
+
}
|
|
137
|
+
isBodyEmpty() {
|
|
138
|
+
return this.bodyLength() === 0;
|
|
139
|
+
}
|
|
140
|
+
bodyLength() {
|
|
141
|
+
const binaryBody = this.binaryBody;
|
|
142
|
+
return binaryBody ? binaryBody.length : 0;
|
|
143
|
+
}
|
|
241
144
|
/**
|
|
242
|
-
*
|
|
243
|
-
*
|
|
145
|
+
* Compute the size of a UTF-8 string by counting its number of bytes
|
|
146
|
+
* (and not the number of characters composing the string)
|
|
244
147
|
*/
|
|
245
|
-
|
|
148
|
+
static sizeOfUTF8(s) {
|
|
149
|
+
return s ? new TextEncoder().encode(s).length : 0;
|
|
150
|
+
}
|
|
151
|
+
static toUnit8Array(cmdAndHeaders, binaryBody) {
|
|
152
|
+
const uint8CmdAndHeaders = new TextEncoder().encode(cmdAndHeaders);
|
|
153
|
+
const nullTerminator = new Uint8Array([0]);
|
|
154
|
+
const uint8Frame = new Uint8Array(uint8CmdAndHeaders.length + binaryBody.length + nullTerminator.length);
|
|
155
|
+
uint8Frame.set(uint8CmdAndHeaders);
|
|
156
|
+
uint8Frame.set(binaryBody, uint8CmdAndHeaders.length);
|
|
157
|
+
uint8Frame.set(nullTerminator, uint8CmdAndHeaders.length + binaryBody.length);
|
|
158
|
+
return uint8Frame;
|
|
159
|
+
}
|
|
246
160
|
/**
|
|
247
|
-
*
|
|
248
|
-
* [type of WebSocket frame]{@link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send#Parameters}
|
|
249
|
-
* is automatically decided by type of the payload.
|
|
250
|
-
* Default is `false`, which should work with all compliant brokers.
|
|
161
|
+
* Serialize a STOMP frame as per STOMP standards, suitable to be sent to the STOMP broker.
|
|
251
162
|
*
|
|
252
|
-
*
|
|
163
|
+
* @internal
|
|
253
164
|
*/
|
|
254
|
-
|
|
165
|
+
static marshall(params) {
|
|
166
|
+
const frame = new FrameImpl(params);
|
|
167
|
+
return frame.serialize();
|
|
168
|
+
}
|
|
255
169
|
/**
|
|
256
|
-
*
|
|
257
|
-
* See issue [https://github.com/stomp-js/stompjs/issues/89]{@link https://github.com/stomp-js/stompjs/issues/89}.
|
|
258
|
-
* This makes incoming WebSocket messages invalid STOMP packets.
|
|
259
|
-
* Setting this flag attempts to reverse the damage by appending a NULL.
|
|
260
|
-
* If the broker splits a large message into multiple WebSocket messages,
|
|
261
|
-
* this flag will cause data loss and abnormal termination of connection.
|
|
262
|
-
*
|
|
263
|
-
* This is not an ideal solution, but a stop gap until the underlying issue is fixed at ReactNative library.
|
|
170
|
+
* Escape header values
|
|
264
171
|
*/
|
|
265
|
-
|
|
172
|
+
static hdrValueEscape(str) {
|
|
173
|
+
return str
|
|
174
|
+
.replace(/\\/g, '\\\\')
|
|
175
|
+
.replace(/\r/g, '\\r')
|
|
176
|
+
.replace(/\n/g, '\\n')
|
|
177
|
+
.replace(/:/g, '\\c');
|
|
178
|
+
}
|
|
266
179
|
/**
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
* It will usually be ACTIVE or INACTIVE.
|
|
270
|
-
* When deactivating it may go from ACTIVE to INACTIVE without entering DEACTIVATING.
|
|
180
|
+
* UnEscape header values
|
|
271
181
|
*/
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
this.onDisconnect = noOp;
|
|
279
|
-
this.onUnhandledMessage = noOp;
|
|
280
|
-
this.onUnhandledReceipt = noOp;
|
|
281
|
-
this.onUnhandledFrame = noOp;
|
|
282
|
-
this.onStompError = noOp;
|
|
283
|
-
this.onWebSocketClose = noOp;
|
|
284
|
-
this.onWebSocketError = noOp;
|
|
285
|
-
this.logRawCommunication = false;
|
|
286
|
-
this.onChangeState = noOp;
|
|
287
|
-
// These parameters would typically get proper values before connect is called
|
|
288
|
-
this.connectHeaders = {};
|
|
289
|
-
this._disconnectHeaders = {};
|
|
290
|
-
// Apply configuration
|
|
291
|
-
this.configure(conf);
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Underlying WebSocket instance, READONLY.
|
|
295
|
-
*/
|
|
296
|
-
get webSocket() {
|
|
297
|
-
return this._stompHandler ? this._stompHandler._webSocket : undefined;
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* Disconnection headers.
|
|
301
|
-
*/
|
|
302
|
-
get disconnectHeaders() {
|
|
303
|
-
return this._disconnectHeaders;
|
|
304
|
-
}
|
|
305
|
-
set disconnectHeaders(value) {
|
|
306
|
-
this._disconnectHeaders = value;
|
|
307
|
-
if (this._stompHandler) {
|
|
308
|
-
this._stompHandler.disconnectHeaders = this._disconnectHeaders;
|
|
182
|
+
static hdrValueUnEscape(str) {
|
|
183
|
+
return str
|
|
184
|
+
.replace(/\\r/g, '\r')
|
|
185
|
+
.replace(/\\n/g, '\n')
|
|
186
|
+
.replace(/\\c/g, ':')
|
|
187
|
+
.replace(/\\\\/g, '\\');
|
|
309
188
|
}
|
|
310
189
|
}
|
|
190
|
+
|
|
311
191
|
/**
|
|
312
|
-
*
|
|
192
|
+
* @internal
|
|
313
193
|
*/
|
|
314
|
-
|
|
315
|
-
return !!this._stompHandler && this._stompHandler.connected;
|
|
316
|
-
}
|
|
194
|
+
const NULL = 0;
|
|
317
195
|
/**
|
|
318
|
-
*
|
|
196
|
+
* @internal
|
|
319
197
|
*/
|
|
320
|
-
|
|
321
|
-
return this._stompHandler ? this._stompHandler.connectedVersion : undefined;
|
|
322
|
-
}
|
|
198
|
+
const LF = 10;
|
|
323
199
|
/**
|
|
324
|
-
*
|
|
200
|
+
* @internal
|
|
325
201
|
*/
|
|
326
|
-
|
|
327
|
-
return this.state === _types__WEBPACK_IMPORTED_MODULE_1__["ActivationState"].ACTIVE;
|
|
328
|
-
}
|
|
329
|
-
_changeState(state) {
|
|
330
|
-
this.state = state;
|
|
331
|
-
this.onChangeState(state);
|
|
332
|
-
}
|
|
202
|
+
const CR = 13;
|
|
333
203
|
/**
|
|
334
|
-
*
|
|
204
|
+
* @internal
|
|
335
205
|
*/
|
|
336
|
-
|
|
337
|
-
// bulk assign all properties to this
|
|
338
|
-
Object.assign(this, conf);
|
|
339
|
-
}
|
|
206
|
+
const COLON = 58;
|
|
340
207
|
/**
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
* it will
|
|
208
|
+
* This is an evented, rec descent parser.
|
|
209
|
+
* A stream of Octets can be passed and whenever it recognizes
|
|
210
|
+
* a complete Frame or an incoming ping it will invoke the registered callbacks.
|
|
211
|
+
*
|
|
212
|
+
* All incoming Octets are fed into _onByte function.
|
|
213
|
+
* Depending on current state the _onByte function keeps changing.
|
|
214
|
+
* Depending on the state it keeps accumulating into _token and _results.
|
|
215
|
+
* State is indicated by current value of _onByte, all states are named as _collect.
|
|
216
|
+
*
|
|
217
|
+
* STOMP standards https://stomp.github.io/stomp-specification-1.2.html
|
|
218
|
+
* imply that all lengths are considered in bytes (instead of string lengths).
|
|
219
|
+
* So, before actual parsing, if the incoming data is String it is converted to Octets.
|
|
220
|
+
* This allows faithful implementation of the protocol and allows NULL Octets to be present in the body.
|
|
221
|
+
*
|
|
222
|
+
* There is no peek function on the incoming data.
|
|
223
|
+
* When a state change occurs based on an Octet without consuming the Octet,
|
|
224
|
+
* the Octet, after state change, is fed again (_reinjectByte).
|
|
225
|
+
* This became possible as the state change can be determined by inspecting just one Octet.
|
|
226
|
+
*
|
|
227
|
+
* There are two modes to collect the body, if content-length header is there then it by counting Octets
|
|
228
|
+
* otherwise it is determined by NULL terminator.
|
|
229
|
+
*
|
|
230
|
+
* Following the standards, the command and headers are converted to Strings
|
|
231
|
+
* and the body is returned as Octets.
|
|
232
|
+
* Headers are returned as an array and not as Hash - to allow multiple occurrence of an header.
|
|
233
|
+
*
|
|
234
|
+
* This parser does not use Regular Expressions as that can only operate on Strings.
|
|
235
|
+
*
|
|
236
|
+
* It handles if multiple STOMP frames are given as one chunk, a frame is split into multiple chunks, or
|
|
237
|
+
* any combination there of. The parser remembers its state (any partial frame) and continues when a new chunk
|
|
238
|
+
* is pushed.
|
|
239
|
+
*
|
|
240
|
+
* Typically the higher level function will convert headers to Hash, handle unescaping of header values
|
|
241
|
+
* (which is protocol version specific), and convert body to text.
|
|
344
242
|
*
|
|
345
|
-
*
|
|
243
|
+
* Check the parser.spec.js to understand cases that this parser is supposed to handle.
|
|
244
|
+
*
|
|
245
|
+
* Part of `@stomp/stompjs`.
|
|
246
|
+
*
|
|
247
|
+
* @internal
|
|
346
248
|
*/
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
this.
|
|
350
|
-
|
|
249
|
+
class Parser {
|
|
250
|
+
constructor(onFrame, onIncomingPing) {
|
|
251
|
+
this.onFrame = onFrame;
|
|
252
|
+
this.onIncomingPing = onIncomingPing;
|
|
253
|
+
this._encoder = new TextEncoder();
|
|
254
|
+
this._decoder = new TextDecoder();
|
|
255
|
+
this._token = [];
|
|
256
|
+
this._initState();
|
|
257
|
+
}
|
|
258
|
+
parseChunk(segment, appendMissingNULLonIncoming = false) {
|
|
259
|
+
let chunk;
|
|
260
|
+
if (segment instanceof ArrayBuffer) {
|
|
261
|
+
chunk = new Uint8Array(segment);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
chunk = this._encoder.encode(segment);
|
|
265
|
+
}
|
|
266
|
+
// See https://github.com/stomp-js/stompjs/issues/89
|
|
267
|
+
// Remove when underlying issue is fixed.
|
|
268
|
+
//
|
|
269
|
+
// Send a NULL byte, if the last byte of a Text frame was not NULL.F
|
|
270
|
+
if (appendMissingNULLonIncoming && chunk[chunk.length - 1] !== 0) {
|
|
271
|
+
const chunkWithNull = new Uint8Array(chunk.length + 1);
|
|
272
|
+
chunkWithNull.set(chunk, 0);
|
|
273
|
+
chunkWithNull[chunk.length] = 0;
|
|
274
|
+
chunk = chunkWithNull;
|
|
275
|
+
}
|
|
276
|
+
// tslint:disable-next-line:prefer-for-of
|
|
277
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
278
|
+
const byte = chunk[i];
|
|
279
|
+
this._onByte(byte);
|
|
280
|
+
}
|
|
351
281
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
282
|
+
// The following implements a simple Rec Descent Parser.
|
|
283
|
+
// The grammar is simple and just one byte tells what should be the next state
|
|
284
|
+
_collectFrame(byte) {
|
|
285
|
+
if (byte === NULL) {
|
|
286
|
+
// Ignore
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
if (byte === CR) {
|
|
290
|
+
// Ignore CR
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (byte === LF) {
|
|
294
|
+
// Incoming Ping
|
|
295
|
+
this.onIncomingPing();
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
this._onByte = this._collectCommand;
|
|
299
|
+
this._reinjectByte(byte);
|
|
355
300
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
_connect() {
|
|
360
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
361
|
-
if (this.connected) {
|
|
362
|
-
this.debug('STOMP: already connected, nothing to do');
|
|
301
|
+
_collectCommand(byte) {
|
|
302
|
+
if (byte === CR) {
|
|
303
|
+
// Ignore CR
|
|
363
304
|
return;
|
|
364
305
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
this.
|
|
306
|
+
if (byte === LF) {
|
|
307
|
+
this._results.command = this._consumeTokenAsUTF8();
|
|
308
|
+
this._onByte = this._collectHeaders;
|
|
368
309
|
return;
|
|
369
310
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
this._connectionWatcher = setTimeout(() => {
|
|
377
|
-
if (this.connected) {
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
// Connection not established, close the underlying socket
|
|
381
|
-
// a reconnection will be attempted
|
|
382
|
-
this.debug(`Connection not established in ${this.connectionTimeout}ms, closing socket`);
|
|
383
|
-
this.forceDisconnect();
|
|
384
|
-
}, this.connectionTimeout);
|
|
311
|
+
this._consumeByte(byte);
|
|
312
|
+
}
|
|
313
|
+
_collectHeaders(byte) {
|
|
314
|
+
if (byte === CR) {
|
|
315
|
+
// Ignore CR
|
|
316
|
+
return;
|
|
385
317
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
connectHeaders: this.connectHeaders,
|
|
393
|
-
disconnectHeaders: this._disconnectHeaders,
|
|
394
|
-
heartbeatIncoming: this.heartbeatIncoming,
|
|
395
|
-
heartbeatOutgoing: this.heartbeatOutgoing,
|
|
396
|
-
splitLargeFrames: this.splitLargeFrames,
|
|
397
|
-
maxWebSocketChunkSize: this.maxWebSocketChunkSize,
|
|
398
|
-
forceBinaryWSFrames: this.forceBinaryWSFrames,
|
|
399
|
-
logRawCommunication: this.logRawCommunication,
|
|
400
|
-
appendMissingNULLonIncoming: this.appendMissingNULLonIncoming,
|
|
401
|
-
discardWebsocketOnCommFailure: this.discardWebsocketOnCommFailure,
|
|
402
|
-
onConnect: frame => {
|
|
403
|
-
// Successfully connected, stop the connection watcher
|
|
404
|
-
if (this._connectionWatcher) {
|
|
405
|
-
clearTimeout(this._connectionWatcher);
|
|
406
|
-
this._connectionWatcher = undefined;
|
|
407
|
-
}
|
|
408
|
-
if (!this.active) {
|
|
409
|
-
this.debug('STOMP got connected while deactivate was issued, will disconnect now');
|
|
410
|
-
this._disposeStompHandler();
|
|
411
|
-
return;
|
|
412
|
-
}
|
|
413
|
-
this.onConnect(frame);
|
|
414
|
-
},
|
|
415
|
-
onDisconnect: frame => {
|
|
416
|
-
this.onDisconnect(frame);
|
|
417
|
-
},
|
|
418
|
-
onStompError: frame => {
|
|
419
|
-
this.onStompError(frame);
|
|
420
|
-
},
|
|
421
|
-
onWebSocketClose: evt => {
|
|
422
|
-
this._stompHandler = undefined; // a new one will be created in case of a reconnect
|
|
423
|
-
if (this.state === _types__WEBPACK_IMPORTED_MODULE_1__["ActivationState"].DEACTIVATING) {
|
|
424
|
-
// Mark deactivation complete
|
|
425
|
-
this._resolveSocketClose();
|
|
426
|
-
this._resolveSocketClose = undefined;
|
|
427
|
-
this._changeState(_types__WEBPACK_IMPORTED_MODULE_1__["ActivationState"].INACTIVE);
|
|
428
|
-
}
|
|
429
|
-
this.onWebSocketClose(evt);
|
|
430
|
-
// The callback is called before attempting to reconnect, this would allow the client
|
|
431
|
-
// to be `deactivated` in the callback.
|
|
432
|
-
if (this.active) {
|
|
433
|
-
this._schedule_reconnect();
|
|
434
|
-
}
|
|
435
|
-
},
|
|
436
|
-
onWebSocketError: evt => {
|
|
437
|
-
this.onWebSocketError(evt);
|
|
438
|
-
},
|
|
439
|
-
onUnhandledMessage: message => {
|
|
440
|
-
this.onUnhandledMessage(message);
|
|
441
|
-
},
|
|
442
|
-
onUnhandledReceipt: frame => {
|
|
443
|
-
this.onUnhandledReceipt(frame);
|
|
444
|
-
},
|
|
445
|
-
onUnhandledFrame: frame => {
|
|
446
|
-
this.onUnhandledFrame(frame);
|
|
447
|
-
},
|
|
448
|
-
});
|
|
449
|
-
this._stompHandler.start();
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
_createWebSocket() {
|
|
453
|
-
let webSocket;
|
|
454
|
-
if (this.webSocketFactory) {
|
|
455
|
-
webSocket = this.webSocketFactory();
|
|
318
|
+
if (byte === LF) {
|
|
319
|
+
this._setupCollectBody();
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
this._onByte = this._collectHeaderKey;
|
|
323
|
+
this._reinjectByte(byte);
|
|
456
324
|
}
|
|
457
|
-
|
|
458
|
-
|
|
325
|
+
_reinjectByte(byte) {
|
|
326
|
+
this._onByte(byte);
|
|
459
327
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
this.
|
|
467
|
-
this._connect();
|
|
468
|
-
}, this.reconnectDelay);
|
|
328
|
+
_collectHeaderKey(byte) {
|
|
329
|
+
if (byte === COLON) {
|
|
330
|
+
this._headerKey = this._consumeTokenAsUTF8();
|
|
331
|
+
this._onByte = this._collectHeaderValue;
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
this._consumeByte(byte);
|
|
469
335
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
*
|
|
475
|
-
* This call is async, it will resolve immediately if there is no underlying active websocket,
|
|
476
|
-
* otherwise, it will resolve after underlying websocket is properly disposed.
|
|
477
|
-
*
|
|
478
|
-
* To reactivate you can call [Client#activate]{@link Client#activate}.
|
|
479
|
-
*/
|
|
480
|
-
deactivate() {
|
|
481
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
482
|
-
let retPromise;
|
|
483
|
-
if (this.state !== _types__WEBPACK_IMPORTED_MODULE_1__["ActivationState"].ACTIVE) {
|
|
484
|
-
this.debug(`Already ${_types__WEBPACK_IMPORTED_MODULE_1__["ActivationState"][this.state]}, ignoring call to deactivate`);
|
|
485
|
-
return Promise.resolve();
|
|
336
|
+
_collectHeaderValue(byte) {
|
|
337
|
+
if (byte === CR) {
|
|
338
|
+
// Ignore CR
|
|
339
|
+
return;
|
|
486
340
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
341
|
+
if (byte === LF) {
|
|
342
|
+
this._results.headers.push([
|
|
343
|
+
this._headerKey,
|
|
344
|
+
this._consumeTokenAsUTF8(),
|
|
345
|
+
]);
|
|
346
|
+
this._headerKey = undefined;
|
|
347
|
+
this._onByte = this._collectHeaders;
|
|
348
|
+
return;
|
|
491
349
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
350
|
+
this._consumeByte(byte);
|
|
351
|
+
}
|
|
352
|
+
_setupCollectBody() {
|
|
353
|
+
const contentLengthHeader = this._results.headers.filter((header) => {
|
|
354
|
+
return header[0] === 'content-length';
|
|
355
|
+
})[0];
|
|
356
|
+
if (contentLengthHeader) {
|
|
357
|
+
this._bodyBytesRemaining = parseInt(contentLengthHeader[1], 10);
|
|
358
|
+
this._onByte = this._collectBodyFixedSize;
|
|
498
359
|
}
|
|
499
360
|
else {
|
|
500
|
-
|
|
501
|
-
this._changeState(_types__WEBPACK_IMPORTED_MODULE_1__["ActivationState"].INACTIVE);
|
|
502
|
-
return Promise.resolve();
|
|
361
|
+
this._onByte = this._collectBodyNullTerminated;
|
|
503
362
|
}
|
|
504
|
-
this._disposeStompHandler();
|
|
505
|
-
return retPromise;
|
|
506
|
-
});
|
|
507
|
-
}
|
|
508
|
-
/**
|
|
509
|
-
* Force disconnect if there is an active connection by directly closing the underlying WebSocket.
|
|
510
|
-
* This is different than a normal disconnect where a DISCONNECT sequence is carried out with the broker.
|
|
511
|
-
* After forcing disconnect, automatic reconnect will be attempted.
|
|
512
|
-
* To stop further reconnects call [Client#deactivate]{@link Client#deactivate} as well.
|
|
513
|
-
*/
|
|
514
|
-
forceDisconnect() {
|
|
515
|
-
if (this._stompHandler) {
|
|
516
|
-
this._stompHandler.forceDisconnect();
|
|
517
363
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
this.
|
|
364
|
+
_collectBodyNullTerminated(byte) {
|
|
365
|
+
if (byte === NULL) {
|
|
366
|
+
this._retrievedBody();
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
this._consumeByte(byte);
|
|
370
|
+
}
|
|
371
|
+
_collectBodyFixedSize(byte) {
|
|
372
|
+
// It is post decrement, so that we discard the trailing NULL octet
|
|
373
|
+
if (this._bodyBytesRemaining-- === 0) {
|
|
374
|
+
this._retrievedBody();
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
this._consumeByte(byte);
|
|
378
|
+
}
|
|
379
|
+
_retrievedBody() {
|
|
380
|
+
this._results.binaryBody = this._consumeTokenAsRaw();
|
|
381
|
+
try {
|
|
382
|
+
this.onFrame(this._results);
|
|
383
|
+
}
|
|
384
|
+
catch (e) {
|
|
385
|
+
console.log(`Ignoring an exception thrown by a frame handler. Original exception: `, e);
|
|
386
|
+
}
|
|
387
|
+
this._initState();
|
|
388
|
+
}
|
|
389
|
+
// Rec Descent Parser helpers
|
|
390
|
+
_consumeByte(byte) {
|
|
391
|
+
this._token.push(byte);
|
|
392
|
+
}
|
|
393
|
+
_consumeTokenAsUTF8() {
|
|
394
|
+
return this._decoder.decode(this._consumeTokenAsRaw());
|
|
395
|
+
}
|
|
396
|
+
_consumeTokenAsRaw() {
|
|
397
|
+
const rawResult = new Uint8Array(this._token);
|
|
398
|
+
this._token = [];
|
|
399
|
+
return rawResult;
|
|
400
|
+
}
|
|
401
|
+
_initState() {
|
|
402
|
+
this._results = {
|
|
403
|
+
command: undefined,
|
|
404
|
+
headers: [],
|
|
405
|
+
binaryBody: undefined,
|
|
406
|
+
};
|
|
407
|
+
this._token = [];
|
|
408
|
+
this._headerKey = undefined;
|
|
409
|
+
this._onByte = this._collectFrame;
|
|
524
410
|
}
|
|
525
411
|
}
|
|
412
|
+
|
|
526
413
|
/**
|
|
527
|
-
*
|
|
528
|
-
* and naming of destinations.
|
|
529
|
-
*
|
|
530
|
-
* STOMP protocol specifies and suggests some headers and also allows broker specific headers.
|
|
531
|
-
*
|
|
532
|
-
* `body` must be String.
|
|
533
|
-
* You will need to covert the payload to string in case it is not string (e.g. JSON).
|
|
534
|
-
*
|
|
535
|
-
* To send a binary message body use binaryBody parameter. It should be a
|
|
536
|
-
* [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array).
|
|
537
|
-
* Sometimes brokers may not support binary frames out of the box.
|
|
538
|
-
* Please check your broker documentation.
|
|
539
|
-
*
|
|
540
|
-
* `content-length` header is automatically added to the STOMP Frame sent to the broker.
|
|
541
|
-
* Set `skipContentLengthHeader` to indicate that `content-length` header should not be added.
|
|
542
|
-
* For binary messages `content-length` header is always added.
|
|
543
|
-
*
|
|
544
|
-
* Caution: The broker will, most likely, report an error and disconnect if message body has NULL octet(s)
|
|
545
|
-
* and `content-length` header is missing.
|
|
546
|
-
*
|
|
547
|
-
* ```javascript
|
|
548
|
-
* client.publish({destination: "/queue/test", headers: {priority: 9}, body: "Hello, STOMP"});
|
|
549
|
-
*
|
|
550
|
-
* // Only destination is mandatory parameter
|
|
551
|
-
* client.publish({destination: "/queue/test", body: "Hello, STOMP"});
|
|
552
|
-
*
|
|
553
|
-
* // Skip content-length header in the frame to the broker
|
|
554
|
-
* client.publish({"/queue/test", body: "Hello, STOMP", skipContentLengthHeader: true});
|
|
555
|
-
*
|
|
556
|
-
* var binaryData = generateBinaryData(); // This need to be of type Uint8Array
|
|
557
|
-
* // setting content-type header is not mandatory, however a good practice
|
|
558
|
-
* client.publish({destination: '/topic/special', binaryBody: binaryData,
|
|
559
|
-
* headers: {'content-type': 'application/octet-stream'}});
|
|
560
|
-
* ```
|
|
414
|
+
* Possible states for the IStompSocket
|
|
561
415
|
*/
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
416
|
+
exports.StompSocketState = void 0;
|
|
417
|
+
(function (StompSocketState) {
|
|
418
|
+
StompSocketState[StompSocketState["CONNECTING"] = 0] = "CONNECTING";
|
|
419
|
+
StompSocketState[StompSocketState["OPEN"] = 1] = "OPEN";
|
|
420
|
+
StompSocketState[StompSocketState["CLOSING"] = 2] = "CLOSING";
|
|
421
|
+
StompSocketState[StompSocketState["CLOSED"] = 3] = "CLOSED";
|
|
422
|
+
})(exports.StompSocketState = exports.StompSocketState || (exports.StompSocketState = {}));
|
|
565
423
|
/**
|
|
566
|
-
*
|
|
567
|
-
* To request an acknowledgement, a `receipt` header needs to be sent with the actual request.
|
|
568
|
-
* The value (say receipt-id) for this header needs to be unique for each use. Typically a sequence, a UUID, a
|
|
569
|
-
* random number or a combination may be used.
|
|
570
|
-
*
|
|
571
|
-
* A complaint broker will send a RECEIPT frame when an operation has actually been completed.
|
|
572
|
-
* The operation needs to be matched based in the value of the receipt-id.
|
|
573
|
-
*
|
|
574
|
-
* This method allow watching for a receipt and invoke the callback
|
|
575
|
-
* when corresponding receipt has been received.
|
|
576
|
-
*
|
|
577
|
-
* The actual {@link FrameImpl} will be passed as parameter to the callback.
|
|
578
|
-
*
|
|
579
|
-
* Example:
|
|
580
|
-
* ```javascript
|
|
581
|
-
* // Subscribing with acknowledgement
|
|
582
|
-
* let receiptId = randomText();
|
|
583
|
-
*
|
|
584
|
-
* client.watchForReceipt(receiptId, function() {
|
|
585
|
-
* // Will be called after server acknowledges
|
|
586
|
-
* });
|
|
587
|
-
*
|
|
588
|
-
* client.subscribe(TEST.destination, onMessage, {receipt: receiptId});
|
|
589
|
-
*
|
|
590
|
-
*
|
|
591
|
-
* // Publishing with acknowledgement
|
|
592
|
-
* receiptId = randomText();
|
|
593
|
-
*
|
|
594
|
-
* client.watchForReceipt(receiptId, function() {
|
|
595
|
-
* // Will be called after server acknowledges
|
|
596
|
-
* });
|
|
597
|
-
* client.publish({destination: TEST.destination, headers: {receipt: receiptId}, body: msg});
|
|
598
|
-
* ```
|
|
424
|
+
* Possible activation state
|
|
599
425
|
*/
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
426
|
+
exports.ActivationState = void 0;
|
|
427
|
+
(function (ActivationState) {
|
|
428
|
+
ActivationState[ActivationState["ACTIVE"] = 0] = "ACTIVE";
|
|
429
|
+
ActivationState[ActivationState["DEACTIVATING"] = 1] = "DEACTIVATING";
|
|
430
|
+
ActivationState[ActivationState["INACTIVE"] = 2] = "INACTIVE";
|
|
431
|
+
})(exports.ActivationState = exports.ActivationState || (exports.ActivationState = {}));
|
|
432
|
+
|
|
603
433
|
/**
|
|
604
|
-
*
|
|
605
|
-
* the {@link IMessage} as argument.
|
|
434
|
+
* Supported STOMP versions
|
|
606
435
|
*
|
|
607
|
-
*
|
|
608
|
-
* To use your own ID, pass it using the headers argument.
|
|
609
|
-
*
|
|
610
|
-
* ```javascript
|
|
611
|
-
* callback = function(message) {
|
|
612
|
-
* // called when the client receives a STOMP message from the server
|
|
613
|
-
* if (message.body) {
|
|
614
|
-
* alert("got message with body " + message.body)
|
|
615
|
-
* } else {
|
|
616
|
-
* alert("got empty message");
|
|
617
|
-
* }
|
|
618
|
-
* });
|
|
619
|
-
*
|
|
620
|
-
* var subscription = client.subscribe("/queue/test", callback);
|
|
621
|
-
*
|
|
622
|
-
* // Explicit subscription id
|
|
623
|
-
* var mySubId = 'my-subscription-id-001';
|
|
624
|
-
* var subscription = client.subscribe(destination, callback, { id: mySubId });
|
|
625
|
-
* ```
|
|
436
|
+
* Part of `@stomp/stompjs`.
|
|
626
437
|
*/
|
|
627
|
-
|
|
628
|
-
|
|
438
|
+
class Versions {
|
|
439
|
+
/**
|
|
440
|
+
* Takes an array of string of versions, typical elements '1.0', '1.1', or '1.2'
|
|
441
|
+
*
|
|
442
|
+
* You will an instance if this class if you want to override supported versions to be declared during
|
|
443
|
+
* STOMP handshake.
|
|
444
|
+
*/
|
|
445
|
+
constructor(versions) {
|
|
446
|
+
this.versions = versions;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Used as part of CONNECT STOMP Frame
|
|
450
|
+
*/
|
|
451
|
+
supportedVersions() {
|
|
452
|
+
return this.versions.join(',');
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Used while creating a WebSocket
|
|
456
|
+
*/
|
|
457
|
+
protocolVersions() {
|
|
458
|
+
return this.versions.map(x => `v${x.replace('.', '')}.stomp`);
|
|
459
|
+
}
|
|
629
460
|
}
|
|
630
461
|
/**
|
|
631
|
-
*
|
|
632
|
-
* `unsubscribe()` directly on {@link StompSubscription} returned by `client.subscribe()`:
|
|
633
|
-
*
|
|
634
|
-
* ```javascript
|
|
635
|
-
* var subscription = client.subscribe(destination, onmessage);
|
|
636
|
-
* // ...
|
|
637
|
-
* subscription.unsubscribe();
|
|
638
|
-
* ```
|
|
639
|
-
*
|
|
640
|
-
* See: http://stomp.github.com/stomp-specification-1.2.html#UNSUBSCRIBE UNSUBSCRIBE Frame
|
|
641
|
-
*/
|
|
642
|
-
unsubscribe(id, headers = {}) {
|
|
643
|
-
this._stompHandler.unsubscribe(id, headers);
|
|
644
|
-
}
|
|
645
|
-
/**
|
|
646
|
-
* Start a transaction, the returned {@link ITransaction} has methods - [commit]{@link ITransaction#commit}
|
|
647
|
-
* and [abort]{@link ITransaction#abort}.
|
|
648
|
-
*
|
|
649
|
-
* `transactionId` is optional, if not passed the library will generate it internally.
|
|
462
|
+
* Indicates protocol version 1.0
|
|
650
463
|
*/
|
|
651
|
-
|
|
652
|
-
return this._stompHandler.begin(transactionId);
|
|
653
|
-
}
|
|
654
|
-
/**
|
|
655
|
-
* Commit a transaction.
|
|
656
|
-
*
|
|
657
|
-
* It is preferable to commit a transaction by calling [commit]{@link ITransaction#commit} directly on
|
|
658
|
-
* {@link ITransaction} returned by [client.begin]{@link Client#begin}.
|
|
659
|
-
*
|
|
660
|
-
* ```javascript
|
|
661
|
-
* var tx = client.begin(txId);
|
|
662
|
-
* //...
|
|
663
|
-
* tx.commit();
|
|
664
|
-
* ```
|
|
665
|
-
*/
|
|
666
|
-
commit(transactionId) {
|
|
667
|
-
this._stompHandler.commit(transactionId);
|
|
668
|
-
}
|
|
464
|
+
Versions.V1_0 = '1.0';
|
|
669
465
|
/**
|
|
670
|
-
*
|
|
671
|
-
* It is preferable to abort a transaction by calling [abort]{@link ITransaction#abort} directly on
|
|
672
|
-
* {@link ITransaction} returned by [client.begin]{@link Client#begin}.
|
|
673
|
-
*
|
|
674
|
-
* ```javascript
|
|
675
|
-
* var tx = client.begin(txId);
|
|
676
|
-
* //...
|
|
677
|
-
* tx.abort();
|
|
678
|
-
* ```
|
|
466
|
+
* Indicates protocol version 1.1
|
|
679
467
|
*/
|
|
680
|
-
|
|
681
|
-
this._stompHandler.abort(transactionId);
|
|
682
|
-
}
|
|
468
|
+
Versions.V1_1 = '1.1';
|
|
683
469
|
/**
|
|
684
|
-
*
|
|
685
|
-
* on the {@link IMessage} handled by a subscription callback:
|
|
686
|
-
*
|
|
687
|
-
* ```javascript
|
|
688
|
-
* var callback = function (message) {
|
|
689
|
-
* // process the message
|
|
690
|
-
* // acknowledge it
|
|
691
|
-
* message.ack();
|
|
692
|
-
* };
|
|
693
|
-
* client.subscribe(destination, callback, {'ack': 'client'});
|
|
694
|
-
* ```
|
|
470
|
+
* Indicates protocol version 1.2
|
|
695
471
|
*/
|
|
696
|
-
|
|
697
|
-
this._stompHandler.ack(messageId, subscriptionId, headers);
|
|
698
|
-
}
|
|
472
|
+
Versions.V1_2 = '1.2';
|
|
699
473
|
/**
|
|
700
|
-
*
|
|
701
|
-
* on the {@link IMessage} handled by a subscription callback:
|
|
702
|
-
*
|
|
703
|
-
* ```javascript
|
|
704
|
-
* var callback = function (message) {
|
|
705
|
-
* // process the message
|
|
706
|
-
* // an error occurs, nack it
|
|
707
|
-
* message.nack();
|
|
708
|
-
* };
|
|
709
|
-
* client.subscribe(destination, callback, {'ack': 'client'});
|
|
710
|
-
* ```
|
|
474
|
+
* @internal
|
|
711
475
|
*/
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
/***/ }),
|
|
476
|
+
Versions.default = new Versions([
|
|
477
|
+
Versions.V1_2,
|
|
478
|
+
Versions.V1_1,
|
|
479
|
+
Versions.V1_0,
|
|
480
|
+
]);
|
|
719
481
|
|
|
720
|
-
/***/ "./src/compatibility/compat-client.ts":
|
|
721
|
-
/*!********************************************!*\
|
|
722
|
-
!*** ./src/compatibility/compat-client.ts ***!
|
|
723
|
-
\********************************************/
|
|
724
|
-
/*! exports provided: CompatClient */
|
|
725
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
726
|
-
|
|
727
|
-
"use strict";
|
|
728
|
-
__webpack_require__.r(__webpack_exports__);
|
|
729
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompatClient", function() { return CompatClient; });
|
|
730
|
-
/* harmony import */ var _client__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../client */ "./src/client.ts");
|
|
731
|
-
/* harmony import */ var _heartbeat_info__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./heartbeat-info */ "./src/compatibility/heartbeat-info.ts");
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
/**
|
|
735
|
-
* Available for backward compatibility, please shift to using {@link Client}.
|
|
736
|
-
*
|
|
737
|
-
* **Deprecated**
|
|
738
|
-
*
|
|
739
|
-
* Part of `@stomp/stompjs`.
|
|
740
|
-
*
|
|
741
|
-
* To upgrade, please follow the [Upgrade Guide](../additional-documentation/upgrading.html)
|
|
742
|
-
*/
|
|
743
|
-
class CompatClient extends _client__WEBPACK_IMPORTED_MODULE_0__["Client"] {
|
|
744
482
|
/**
|
|
745
|
-
* Available for backward compatibility, please shift to using {@link Client}
|
|
746
|
-
* and [Client#webSocketFactory]{@link Client#webSocketFactory}.
|
|
747
|
-
*
|
|
748
|
-
* **Deprecated**
|
|
749
|
-
*
|
|
750
483
|
* @internal
|
|
751
484
|
*/
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
485
|
+
function augmentWebsocket(webSocket, debug) {
|
|
486
|
+
webSocket.terminate = function () {
|
|
487
|
+
const noOp = () => { };
|
|
488
|
+
// set all callbacks to no op
|
|
489
|
+
this.onerror = noOp;
|
|
490
|
+
this.onmessage = noOp;
|
|
491
|
+
this.onopen = noOp;
|
|
492
|
+
const ts = new Date();
|
|
493
|
+
const id = Math.random().toString().substring(2, 8); // A simulated id
|
|
494
|
+
const origOnClose = this.onclose;
|
|
495
|
+
// Track delay in actual closure of the socket
|
|
496
|
+
this.onclose = closeEvent => {
|
|
497
|
+
const delay = new Date().getTime() - ts.getTime();
|
|
498
|
+
debug(`Discarded socket (#${id}) closed after ${delay}ms, with code/reason: ${closeEvent.code}/${closeEvent.reason}`);
|
|
499
|
+
};
|
|
500
|
+
this.close();
|
|
501
|
+
origOnClose?.call(webSocket, {
|
|
502
|
+
code: 4001,
|
|
503
|
+
reason: `Quick discarding socket (#${id}) without waiting for the shutdown sequence.`,
|
|
504
|
+
wasClean: false,
|
|
505
|
+
});
|
|
764
506
|
};
|
|
765
507
|
}
|
|
766
|
-
|
|
767
|
-
let closeEventCallback;
|
|
768
|
-
let connectCallback;
|
|
769
|
-
let errorCallback;
|
|
770
|
-
let headers = {};
|
|
771
|
-
if (args.length < 2) {
|
|
772
|
-
throw new Error('Connect requires at least 2 arguments');
|
|
773
|
-
}
|
|
774
|
-
if (typeof args[1] === 'function') {
|
|
775
|
-
[headers, connectCallback, errorCallback, closeEventCallback] = args;
|
|
776
|
-
}
|
|
777
|
-
else {
|
|
778
|
-
switch (args.length) {
|
|
779
|
-
case 6:
|
|
780
|
-
[
|
|
781
|
-
headers.login,
|
|
782
|
-
headers.passcode,
|
|
783
|
-
connectCallback,
|
|
784
|
-
errorCallback,
|
|
785
|
-
closeEventCallback,
|
|
786
|
-
headers.host,
|
|
787
|
-
] = args;
|
|
788
|
-
break;
|
|
789
|
-
default:
|
|
790
|
-
[
|
|
791
|
-
headers.login,
|
|
792
|
-
headers.passcode,
|
|
793
|
-
connectCallback,
|
|
794
|
-
errorCallback,
|
|
795
|
-
closeEventCallback,
|
|
796
|
-
] = args;
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
return [headers, connectCallback, errorCallback, closeEventCallback];
|
|
800
|
-
}
|
|
508
|
+
|
|
801
509
|
/**
|
|
802
|
-
*
|
|
803
|
-
*
|
|
804
|
-
* **Deprecated**
|
|
805
|
-
*
|
|
806
|
-
* The `connect` method accepts different number of arguments and types. See the Overloads list. Use the
|
|
807
|
-
* version with headers to pass your broker specific options.
|
|
808
|
-
*
|
|
809
|
-
* overloads:
|
|
810
|
-
* - connect(headers, connectCallback)
|
|
811
|
-
* - connect(headers, connectCallback, errorCallback)
|
|
812
|
-
* - connect(login, passcode, connectCallback)
|
|
813
|
-
* - connect(login, passcode, connectCallback, errorCallback)
|
|
814
|
-
* - connect(login, passcode, connectCallback, errorCallback, closeEventCallback)
|
|
815
|
-
* - connect(login, passcode, connectCallback, errorCallback, closeEventCallback, host)
|
|
510
|
+
* The STOMP protocol handler
|
|
816
511
|
*
|
|
817
|
-
*
|
|
818
|
-
* - headers, see [Client#connectHeaders]{@link Client#connectHeaders}
|
|
819
|
-
* - connectCallback, see [Client#onConnect]{@link Client#onConnect}
|
|
820
|
-
* - errorCallback, see [Client#onStompError]{@link Client#onStompError}
|
|
821
|
-
* - closeEventCallback, see [Client#onWebSocketClose]{@link Client#onWebSocketClose}
|
|
822
|
-
* - login [String], see [Client#connectHeaders](../classes/Client.html#connectHeaders)
|
|
823
|
-
* - passcode [String], [Client#connectHeaders](../classes/Client.html#connectHeaders)
|
|
824
|
-
* - host [String], see [Client#connectHeaders](../classes/Client.html#connectHeaders)
|
|
512
|
+
* Part of `@stomp/stompjs`.
|
|
825
513
|
*
|
|
826
|
-
*
|
|
514
|
+
* @internal
|
|
827
515
|
*/
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
this.
|
|
516
|
+
class StompHandler {
|
|
517
|
+
constructor(_client, _webSocket, config) {
|
|
518
|
+
this._client = _client;
|
|
519
|
+
this._webSocket = _webSocket;
|
|
520
|
+
this._connected = false;
|
|
521
|
+
this._serverFrameHandlers = {
|
|
522
|
+
// [CONNECTED Frame](http://stomp.github.com/stomp-specification-1.2.html#CONNECTED_Frame)
|
|
523
|
+
CONNECTED: frame => {
|
|
524
|
+
this.debug(`connected to server ${frame.headers.server}`);
|
|
525
|
+
this._connected = true;
|
|
526
|
+
this._connectedVersion = frame.headers.version;
|
|
527
|
+
// STOMP version 1.2 needs header values to be escaped
|
|
528
|
+
if (this._connectedVersion === Versions.V1_2) {
|
|
529
|
+
this._escapeHeaderValues = true;
|
|
530
|
+
}
|
|
531
|
+
this._setupHeartbeat(frame.headers);
|
|
532
|
+
this.onConnect(frame);
|
|
533
|
+
},
|
|
534
|
+
// [MESSAGE Frame](http://stomp.github.com/stomp-specification-1.2.html#MESSAGE)
|
|
535
|
+
MESSAGE: frame => {
|
|
536
|
+
// the callback is registered when the client calls
|
|
537
|
+
// `subscribe()`.
|
|
538
|
+
// If there is no registered subscription for the received message,
|
|
539
|
+
// the default `onUnhandledMessage` callback is used that the client can set.
|
|
540
|
+
// This is useful for subscriptions that are automatically created
|
|
541
|
+
// on the browser side (e.g. [RabbitMQ's temporary
|
|
542
|
+
// queues](http://www.rabbitmq.com/stomp.html)).
|
|
543
|
+
const subscription = frame.headers.subscription;
|
|
544
|
+
const onReceive = this._subscriptions[subscription] || this.onUnhandledMessage;
|
|
545
|
+
// bless the frame to be a Message
|
|
546
|
+
const message = frame;
|
|
547
|
+
const client = this;
|
|
548
|
+
const messageId = this._connectedVersion === Versions.V1_2
|
|
549
|
+
? message.headers.ack
|
|
550
|
+
: message.headers['message-id'];
|
|
551
|
+
// add `ack()` and `nack()` methods directly to the returned frame
|
|
552
|
+
// so that a simple call to `message.ack()` can acknowledge the message.
|
|
553
|
+
message.ack = (headers = {}) => {
|
|
554
|
+
return client.ack(messageId, subscription, headers);
|
|
555
|
+
};
|
|
556
|
+
message.nack = (headers = {}) => {
|
|
557
|
+
return client.nack(messageId, subscription, headers);
|
|
558
|
+
};
|
|
559
|
+
onReceive(message);
|
|
560
|
+
},
|
|
561
|
+
// [RECEIPT Frame](http://stomp.github.com/stomp-specification-1.2.html#RECEIPT)
|
|
562
|
+
RECEIPT: frame => {
|
|
563
|
+
const callback = this._receiptWatchers[frame.headers['receipt-id']];
|
|
564
|
+
if (callback) {
|
|
565
|
+
callback(frame);
|
|
566
|
+
// Server will acknowledge only once, remove the callback
|
|
567
|
+
delete this._receiptWatchers[frame.headers['receipt-id']];
|
|
568
|
+
}
|
|
569
|
+
else {
|
|
570
|
+
this.onUnhandledReceipt(frame);
|
|
571
|
+
}
|
|
572
|
+
},
|
|
573
|
+
// [ERROR Frame](http://stomp.github.com/stomp-specification-1.2.html#ERROR)
|
|
574
|
+
ERROR: frame => {
|
|
575
|
+
this.onStompError(frame);
|
|
576
|
+
},
|
|
577
|
+
};
|
|
578
|
+
// used to index subscribers
|
|
579
|
+
this._counter = 0;
|
|
580
|
+
// subscription callbacks indexed by subscriber's ID
|
|
581
|
+
this._subscriptions = {};
|
|
582
|
+
// receipt-watchers indexed by receipts-ids
|
|
583
|
+
this._receiptWatchers = {};
|
|
584
|
+
this._partialData = '';
|
|
585
|
+
this._escapeHeaderValues = false;
|
|
586
|
+
this._lastServerActivityTS = Date.now();
|
|
587
|
+
this.debug = config.debug;
|
|
588
|
+
this.stompVersions = config.stompVersions;
|
|
589
|
+
this.connectHeaders = config.connectHeaders;
|
|
590
|
+
this.disconnectHeaders = config.disconnectHeaders;
|
|
591
|
+
this.heartbeatIncoming = config.heartbeatIncoming;
|
|
592
|
+
this.heartbeatOutgoing = config.heartbeatOutgoing;
|
|
593
|
+
this.splitLargeFrames = config.splitLargeFrames;
|
|
594
|
+
this.maxWebSocketChunkSize = config.maxWebSocketChunkSize;
|
|
595
|
+
this.forceBinaryWSFrames = config.forceBinaryWSFrames;
|
|
596
|
+
this.logRawCommunication = config.logRawCommunication;
|
|
597
|
+
this.appendMissingNULLonIncoming = config.appendMissingNULLonIncoming;
|
|
598
|
+
this.discardWebsocketOnCommFailure = config.discardWebsocketOnCommFailure;
|
|
599
|
+
this.onConnect = config.onConnect;
|
|
600
|
+
this.onDisconnect = config.onDisconnect;
|
|
601
|
+
this.onStompError = config.onStompError;
|
|
602
|
+
this.onWebSocketClose = config.onWebSocketClose;
|
|
603
|
+
this.onWebSocketError = config.onWebSocketError;
|
|
604
|
+
this.onUnhandledMessage = config.onUnhandledMessage;
|
|
605
|
+
this.onUnhandledReceipt = config.onUnhandledReceipt;
|
|
606
|
+
this.onUnhandledFrame = config.onUnhandledFrame;
|
|
607
|
+
}
|
|
608
|
+
get connectedVersion() {
|
|
609
|
+
return this._connectedVersion;
|
|
610
|
+
}
|
|
611
|
+
get connected() {
|
|
612
|
+
return this._connected;
|
|
613
|
+
}
|
|
614
|
+
start() {
|
|
615
|
+
const parser = new Parser(
|
|
616
|
+
// On Frame
|
|
617
|
+
rawFrame => {
|
|
618
|
+
const frame = FrameImpl.fromRawFrame(rawFrame, this._escapeHeaderValues);
|
|
619
|
+
// if this.logRawCommunication is set, the rawChunk is logged at this._webSocket.onmessage
|
|
620
|
+
if (!this.logRawCommunication) {
|
|
621
|
+
this.debug(`<<< ${frame}`);
|
|
622
|
+
}
|
|
623
|
+
const serverFrameHandler = this._serverFrameHandlers[frame.command] || this.onUnhandledFrame;
|
|
624
|
+
serverFrameHandler(frame);
|
|
625
|
+
},
|
|
626
|
+
// On Incoming Ping
|
|
627
|
+
() => {
|
|
628
|
+
this.debug('<<< PONG');
|
|
629
|
+
});
|
|
630
|
+
this._webSocket.onmessage = (evt) => {
|
|
631
|
+
this.debug('Received data');
|
|
632
|
+
this._lastServerActivityTS = Date.now();
|
|
633
|
+
if (this.logRawCommunication) {
|
|
634
|
+
const rawChunkAsString = evt.data instanceof ArrayBuffer
|
|
635
|
+
? new TextDecoder().decode(evt.data)
|
|
636
|
+
: evt.data;
|
|
637
|
+
this.debug(`<<< ${rawChunkAsString}`);
|
|
638
|
+
}
|
|
639
|
+
parser.parseChunk(evt.data, this.appendMissingNULLonIncoming);
|
|
640
|
+
};
|
|
641
|
+
this._webSocket.onclose = (closeEvent) => {
|
|
642
|
+
this.debug(`Connection closed to ${this._client.brokerURL}`);
|
|
643
|
+
this._cleanUp();
|
|
644
|
+
this.onWebSocketClose(closeEvent);
|
|
645
|
+
};
|
|
646
|
+
this._webSocket.onerror = (errorEvent) => {
|
|
647
|
+
this.onWebSocketError(errorEvent);
|
|
648
|
+
};
|
|
649
|
+
this._webSocket.onopen = () => {
|
|
650
|
+
// Clone before updating
|
|
651
|
+
const connectHeaders = Object.assign({}, this.connectHeaders);
|
|
652
|
+
this.debug('Web Socket Opened...');
|
|
653
|
+
connectHeaders['accept-version'] = this.stompVersions.supportedVersions();
|
|
654
|
+
connectHeaders['heart-beat'] = [
|
|
655
|
+
this.heartbeatOutgoing,
|
|
656
|
+
this.heartbeatIncoming,
|
|
657
|
+
].join(',');
|
|
658
|
+
this._transmit({ command: 'CONNECT', headers: connectHeaders });
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
_setupHeartbeat(headers) {
|
|
662
|
+
if (headers.version !== Versions.V1_1 &&
|
|
663
|
+
headers.version !== Versions.V1_2) {
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
// It is valid for the server to not send this header
|
|
667
|
+
// https://stomp.github.io/stomp-specification-1.2.html#Heart-beating
|
|
668
|
+
if (!headers['heart-beat']) {
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
// heart-beat header received from the server looks like:
|
|
672
|
+
//
|
|
673
|
+
// heart-beat: sx, sy
|
|
674
|
+
const [serverOutgoing, serverIncoming] = headers['heart-beat']
|
|
675
|
+
.split(',')
|
|
676
|
+
.map((v) => parseInt(v, 10));
|
|
677
|
+
if (this.heartbeatOutgoing !== 0 && serverIncoming !== 0) {
|
|
678
|
+
const ttl = Math.max(this.heartbeatOutgoing, serverIncoming);
|
|
679
|
+
this.debug(`send PING every ${ttl}ms`);
|
|
680
|
+
this._pinger = setInterval(() => {
|
|
681
|
+
if (this._webSocket.readyState === exports.StompSocketState.OPEN) {
|
|
682
|
+
this._webSocket.send(BYTE.LF);
|
|
683
|
+
this.debug('>>> PING');
|
|
684
|
+
}
|
|
685
|
+
}, ttl);
|
|
686
|
+
}
|
|
687
|
+
if (this.heartbeatIncoming !== 0 && serverOutgoing !== 0) {
|
|
688
|
+
const ttl = Math.max(this.heartbeatIncoming, serverOutgoing);
|
|
689
|
+
this.debug(`check PONG every ${ttl}ms`);
|
|
690
|
+
this._ponger = setInterval(() => {
|
|
691
|
+
const delta = Date.now() - this._lastServerActivityTS;
|
|
692
|
+
// We wait twice the TTL to be flexible on window's setInterval calls
|
|
693
|
+
if (delta > ttl * 2) {
|
|
694
|
+
this.debug(`did not receive server activity for the last ${delta}ms`);
|
|
695
|
+
this._closeOrDiscardWebsocket();
|
|
696
|
+
}
|
|
697
|
+
}, ttl);
|
|
698
|
+
}
|
|
832
699
|
}
|
|
833
|
-
|
|
834
|
-
this.
|
|
700
|
+
_closeOrDiscardWebsocket() {
|
|
701
|
+
if (this.discardWebsocketOnCommFailure) {
|
|
702
|
+
this.debug('Discarding websocket, the underlying socket may linger for a while');
|
|
703
|
+
this.discardWebsocket();
|
|
704
|
+
}
|
|
705
|
+
else {
|
|
706
|
+
this.debug('Issuing close on the websocket');
|
|
707
|
+
this._closeWebsocket();
|
|
708
|
+
}
|
|
835
709
|
}
|
|
836
|
-
|
|
837
|
-
this.
|
|
710
|
+
forceDisconnect() {
|
|
711
|
+
if (this._webSocket) {
|
|
712
|
+
if (this._webSocket.readyState === exports.StompSocketState.CONNECTING ||
|
|
713
|
+
this._webSocket.readyState === exports.StompSocketState.OPEN) {
|
|
714
|
+
this._closeOrDiscardWebsocket();
|
|
715
|
+
}
|
|
716
|
+
}
|
|
838
717
|
}
|
|
839
|
-
|
|
840
|
-
this.
|
|
718
|
+
_closeWebsocket() {
|
|
719
|
+
this._webSocket.onmessage = () => { }; // ignore messages
|
|
720
|
+
this._webSocket.close();
|
|
841
721
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
722
|
+
discardWebsocket() {
|
|
723
|
+
if (typeof this._webSocket.terminate !== 'function') {
|
|
724
|
+
augmentWebsocket(this._webSocket, (msg) => this.debug(msg));
|
|
725
|
+
}
|
|
726
|
+
// @ts-ignore - this method will be there at this stage
|
|
727
|
+
this._webSocket.terminate();
|
|
728
|
+
}
|
|
729
|
+
_transmit(params) {
|
|
730
|
+
const { command, headers, body, binaryBody, skipContentLengthHeader } = params;
|
|
731
|
+
const frame = new FrameImpl({
|
|
732
|
+
command,
|
|
733
|
+
headers,
|
|
734
|
+
body,
|
|
735
|
+
binaryBody,
|
|
736
|
+
escapeHeaderValues: this._escapeHeaderValues,
|
|
737
|
+
skipContentLengthHeader,
|
|
738
|
+
});
|
|
739
|
+
let rawChunk = frame.serialize();
|
|
740
|
+
if (this.logRawCommunication) {
|
|
741
|
+
this.debug(`>>> ${rawChunk}`);
|
|
742
|
+
}
|
|
743
|
+
else {
|
|
744
|
+
this.debug(`>>> ${frame}`);
|
|
745
|
+
}
|
|
746
|
+
if (this.forceBinaryWSFrames && typeof rawChunk === 'string') {
|
|
747
|
+
rawChunk = new TextEncoder().encode(rawChunk);
|
|
748
|
+
}
|
|
749
|
+
if (typeof rawChunk !== 'string' || !this.splitLargeFrames) {
|
|
750
|
+
this._webSocket.send(rawChunk);
|
|
751
|
+
}
|
|
752
|
+
else {
|
|
753
|
+
let out = rawChunk;
|
|
754
|
+
while (out.length > 0) {
|
|
755
|
+
const chunk = out.substring(0, this.maxWebSocketChunkSize);
|
|
756
|
+
out = out.substring(this.maxWebSocketChunkSize);
|
|
757
|
+
this._webSocket.send(chunk);
|
|
758
|
+
this.debug(`chunk sent = ${chunk.length}, remaining = ${out.length}`);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
858
761
|
}
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
const skipContentLengthHeader = headers['content-length'] === false;
|
|
885
|
-
if (skipContentLengthHeader) {
|
|
886
|
-
delete headers['content-length'];
|
|
887
|
-
}
|
|
888
|
-
this.publish({
|
|
889
|
-
destination,
|
|
890
|
-
headers: headers,
|
|
891
|
-
body,
|
|
892
|
-
skipContentLengthHeader,
|
|
893
|
-
});
|
|
894
|
-
}
|
|
895
|
-
/**
|
|
896
|
-
* Available for backward compatibility, renamed to [Client#reconnectDelay]{@link Client#reconnectDelay}.
|
|
897
|
-
*
|
|
898
|
-
* **Deprecated**
|
|
899
|
-
*/
|
|
900
|
-
set reconnect_delay(value) {
|
|
901
|
-
this.reconnectDelay = value;
|
|
902
|
-
}
|
|
903
|
-
/**
|
|
904
|
-
* Available for backward compatibility, renamed to [Client#webSocket]{@link Client#webSocket}.
|
|
905
|
-
*
|
|
906
|
-
* **Deprecated**
|
|
907
|
-
*/
|
|
908
|
-
get ws() {
|
|
909
|
-
return this.webSocket;
|
|
910
|
-
}
|
|
911
|
-
/**
|
|
912
|
-
* Available for backward compatibility, renamed to [Client#connectedVersion]{@link Client#connectedVersion}.
|
|
913
|
-
*
|
|
914
|
-
* **Deprecated**
|
|
915
|
-
*/
|
|
916
|
-
get version() {
|
|
917
|
-
return this.connectedVersion;
|
|
918
|
-
}
|
|
919
|
-
/**
|
|
920
|
-
* Available for backward compatibility, renamed to [Client#onUnhandledMessage]{@link Client#onUnhandledMessage}.
|
|
921
|
-
*
|
|
922
|
-
* **Deprecated**
|
|
923
|
-
*/
|
|
924
|
-
get onreceive() {
|
|
925
|
-
return this.onUnhandledMessage;
|
|
926
|
-
}
|
|
927
|
-
/**
|
|
928
|
-
* Available for backward compatibility, renamed to [Client#onUnhandledMessage]{@link Client#onUnhandledMessage}.
|
|
929
|
-
*
|
|
930
|
-
* **Deprecated**
|
|
931
|
-
*/
|
|
932
|
-
set onreceive(value) {
|
|
933
|
-
this.onUnhandledMessage = value;
|
|
934
|
-
}
|
|
935
|
-
/**
|
|
936
|
-
* Available for backward compatibility, renamed to [Client#onUnhandledReceipt]{@link Client#onUnhandledReceipt}.
|
|
937
|
-
* Prefer using [Client#watchForReceipt]{@link Client#watchForReceipt}.
|
|
938
|
-
*
|
|
939
|
-
* **Deprecated**
|
|
940
|
-
*/
|
|
941
|
-
get onreceipt() {
|
|
942
|
-
return this.onUnhandledReceipt;
|
|
943
|
-
}
|
|
944
|
-
/**
|
|
945
|
-
* Available for backward compatibility, renamed to [Client#onUnhandledReceipt]{@link Client#onUnhandledReceipt}.
|
|
946
|
-
*
|
|
947
|
-
* **Deprecated**
|
|
948
|
-
*/
|
|
949
|
-
set onreceipt(value) {
|
|
950
|
-
this.onUnhandledReceipt = value;
|
|
951
|
-
}
|
|
952
|
-
/**
|
|
953
|
-
* Available for backward compatibility, renamed to [Client#heartbeatIncoming]{@link Client#heartbeatIncoming}
|
|
954
|
-
* [Client#heartbeatOutgoing]{@link Client#heartbeatOutgoing}.
|
|
955
|
-
*
|
|
956
|
-
* **Deprecated**
|
|
957
|
-
*/
|
|
958
|
-
get heartbeat() {
|
|
959
|
-
return this._heartbeatInfo;
|
|
960
|
-
}
|
|
961
|
-
/**
|
|
962
|
-
* Available for backward compatibility, renamed to [Client#heartbeatIncoming]{@link Client#heartbeatIncoming}
|
|
963
|
-
* [Client#heartbeatOutgoing]{@link Client#heartbeatOutgoing}.
|
|
964
|
-
*
|
|
965
|
-
* **Deprecated**
|
|
966
|
-
*/
|
|
967
|
-
set heartbeat(value) {
|
|
968
|
-
this.heartbeatIncoming = value.incoming;
|
|
969
|
-
this.heartbeatOutgoing = value.outgoing;
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
/***/ }),
|
|
975
|
-
|
|
976
|
-
/***/ "./src/compatibility/heartbeat-info.ts":
|
|
977
|
-
/*!*********************************************!*\
|
|
978
|
-
!*** ./src/compatibility/heartbeat-info.ts ***!
|
|
979
|
-
\*********************************************/
|
|
980
|
-
/*! exports provided: HeartbeatInfo */
|
|
981
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
982
|
-
|
|
983
|
-
"use strict";
|
|
984
|
-
__webpack_require__.r(__webpack_exports__);
|
|
985
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HeartbeatInfo", function() { return HeartbeatInfo; });
|
|
986
|
-
/**
|
|
987
|
-
* Part of `@stomp/stompjs`.
|
|
988
|
-
*
|
|
989
|
-
* @internal
|
|
990
|
-
*/
|
|
991
|
-
class HeartbeatInfo {
|
|
992
|
-
constructor(client) {
|
|
993
|
-
this.client = client;
|
|
994
|
-
}
|
|
995
|
-
get outgoing() {
|
|
996
|
-
return this.client.heartbeatOutgoing;
|
|
997
|
-
}
|
|
998
|
-
set outgoing(value) {
|
|
999
|
-
this.client.heartbeatOutgoing = value;
|
|
1000
|
-
}
|
|
1001
|
-
get incoming() {
|
|
1002
|
-
return this.client.heartbeatIncoming;
|
|
1003
|
-
}
|
|
1004
|
-
set incoming(value) {
|
|
1005
|
-
this.client.heartbeatIncoming = value;
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
/***/ }),
|
|
1011
|
-
|
|
1012
|
-
/***/ "./src/compatibility/stomp.ts":
|
|
1013
|
-
/*!************************************!*\
|
|
1014
|
-
!*** ./src/compatibility/stomp.ts ***!
|
|
1015
|
-
\************************************/
|
|
1016
|
-
/*! exports provided: Stomp */
|
|
1017
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1018
|
-
|
|
1019
|
-
"use strict";
|
|
1020
|
-
__webpack_require__.r(__webpack_exports__);
|
|
1021
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Stomp", function() { return Stomp; });
|
|
1022
|
-
/* harmony import */ var _versions__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../versions */ "./src/versions.ts");
|
|
1023
|
-
/* harmony import */ var _compat_client__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./compat-client */ "./src/compatibility/compat-client.ts");
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
/**
|
|
1027
|
-
* STOMP Class, acts like a factory to create {@link Client}.
|
|
1028
|
-
*
|
|
1029
|
-
* Part of `@stomp/stompjs`.
|
|
1030
|
-
*
|
|
1031
|
-
* **Deprecated**
|
|
1032
|
-
*
|
|
1033
|
-
* It will be removed in next major version. Please switch to {@link Client}.
|
|
1034
|
-
*/
|
|
1035
|
-
class Stomp {
|
|
1036
|
-
/**
|
|
1037
|
-
* This method creates a WebSocket client that is connected to
|
|
1038
|
-
* the STOMP server located at the url.
|
|
1039
|
-
*
|
|
1040
|
-
* ```javascript
|
|
1041
|
-
* var url = "ws://localhost:61614/stomp";
|
|
1042
|
-
* var client = Stomp.client(url);
|
|
1043
|
-
* ```
|
|
1044
|
-
*
|
|
1045
|
-
* **Deprecated**
|
|
1046
|
-
*
|
|
1047
|
-
* It will be removed in next major version. Please switch to {@link Client}
|
|
1048
|
-
* using [Client#brokerURL]{@link Client#brokerURL}.
|
|
1049
|
-
*/
|
|
1050
|
-
static client(url, protocols) {
|
|
1051
|
-
// This is a hack to allow another implementation than the standard
|
|
1052
|
-
// HTML5 WebSocket class.
|
|
1053
|
-
//
|
|
1054
|
-
// It is possible to use another class by calling
|
|
1055
|
-
//
|
|
1056
|
-
// Stomp.WebSocketClass = MozWebSocket
|
|
1057
|
-
//
|
|
1058
|
-
// *prior* to call `Stomp.client()`.
|
|
1059
|
-
//
|
|
1060
|
-
// This hack is deprecated and `Stomp.over()` method should be used
|
|
1061
|
-
// instead.
|
|
1062
|
-
// See remarks on the function Stomp.over
|
|
1063
|
-
if (protocols == null) {
|
|
1064
|
-
protocols = _versions__WEBPACK_IMPORTED_MODULE_0__["Versions"].default.protocolVersions();
|
|
1065
|
-
}
|
|
1066
|
-
const wsFn = () => {
|
|
1067
|
-
const klass = Stomp.WebSocketClass || WebSocket;
|
|
1068
|
-
return new klass(url, protocols);
|
|
1069
|
-
};
|
|
1070
|
-
return new _compat_client__WEBPACK_IMPORTED_MODULE_1__["CompatClient"](wsFn);
|
|
1071
|
-
}
|
|
1072
|
-
/**
|
|
1073
|
-
* This method is an alternative to [Stomp#client]{@link Stomp#client} to let the user
|
|
1074
|
-
* specify the WebSocket to use (either a standard HTML5 WebSocket or
|
|
1075
|
-
* a similar object).
|
|
1076
|
-
*
|
|
1077
|
-
* In order to support reconnection, the function Client._connect should be callable more than once.
|
|
1078
|
-
* While reconnecting
|
|
1079
|
-
* a new instance of underlying transport (TCP Socket, WebSocket or SockJS) will be needed. So, this function
|
|
1080
|
-
* alternatively allows passing a function that should return a new instance of the underlying socket.
|
|
1081
|
-
*
|
|
1082
|
-
* ```javascript
|
|
1083
|
-
* var client = Stomp.over(function(){
|
|
1084
|
-
* return new WebSocket('ws://localhost:15674/ws')
|
|
1085
|
-
* });
|
|
1086
|
-
* ```
|
|
1087
|
-
*
|
|
1088
|
-
* **Deprecated**
|
|
1089
|
-
*
|
|
1090
|
-
* It will be removed in next major version. Please switch to {@link Client}
|
|
1091
|
-
* using [Client#webSocketFactory]{@link Client#webSocketFactory}.
|
|
1092
|
-
*/
|
|
1093
|
-
static over(ws) {
|
|
1094
|
-
let wsFn;
|
|
1095
|
-
if (typeof ws === 'function') {
|
|
1096
|
-
wsFn = ws;
|
|
762
|
+
dispose() {
|
|
763
|
+
if (this.connected) {
|
|
764
|
+
try {
|
|
765
|
+
// clone before updating
|
|
766
|
+
const disconnectHeaders = Object.assign({}, this.disconnectHeaders);
|
|
767
|
+
if (!disconnectHeaders.receipt) {
|
|
768
|
+
disconnectHeaders.receipt = `close-${this._counter++}`;
|
|
769
|
+
}
|
|
770
|
+
this.watchForReceipt(disconnectHeaders.receipt, frame => {
|
|
771
|
+
this._closeWebsocket();
|
|
772
|
+
this._cleanUp();
|
|
773
|
+
this.onDisconnect(frame);
|
|
774
|
+
});
|
|
775
|
+
this._transmit({ command: 'DISCONNECT', headers: disconnectHeaders });
|
|
776
|
+
}
|
|
777
|
+
catch (error) {
|
|
778
|
+
this.debug(`Ignoring error during disconnect ${error}`);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
else {
|
|
782
|
+
if (this._webSocket.readyState === exports.StompSocketState.CONNECTING ||
|
|
783
|
+
this._webSocket.readyState === exports.StompSocketState.OPEN) {
|
|
784
|
+
this._closeWebsocket();
|
|
785
|
+
}
|
|
786
|
+
}
|
|
1097
787
|
}
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
788
|
+
_cleanUp() {
|
|
789
|
+
this._connected = false;
|
|
790
|
+
if (this._pinger) {
|
|
791
|
+
clearInterval(this._pinger);
|
|
792
|
+
this._pinger = undefined;
|
|
793
|
+
}
|
|
794
|
+
if (this._ponger) {
|
|
795
|
+
clearInterval(this._ponger);
|
|
796
|
+
this._ponger = undefined;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
publish(params) {
|
|
800
|
+
const { destination, headers, body, binaryBody, skipContentLengthHeader } = params;
|
|
801
|
+
const hdrs = Object.assign({ destination }, headers);
|
|
802
|
+
this._transmit({
|
|
803
|
+
command: 'SEND',
|
|
804
|
+
headers: hdrs,
|
|
805
|
+
body,
|
|
806
|
+
binaryBody,
|
|
807
|
+
skipContentLengthHeader,
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
watchForReceipt(receiptId, callback) {
|
|
811
|
+
this._receiptWatchers[receiptId] = callback;
|
|
812
|
+
}
|
|
813
|
+
subscribe(destination, callback, headers = {}) {
|
|
814
|
+
headers = Object.assign({}, headers);
|
|
815
|
+
if (!headers.id) {
|
|
816
|
+
headers.id = `sub-${this._counter++}`;
|
|
817
|
+
}
|
|
818
|
+
headers.destination = destination;
|
|
819
|
+
this._subscriptions[headers.id] = callback;
|
|
820
|
+
this._transmit({ command: 'SUBSCRIBE', headers });
|
|
821
|
+
const client = this;
|
|
822
|
+
return {
|
|
823
|
+
id: headers.id,
|
|
824
|
+
unsubscribe(hdrs) {
|
|
825
|
+
return client.unsubscribe(headers.id, hdrs);
|
|
826
|
+
},
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
unsubscribe(id, headers = {}) {
|
|
830
|
+
headers = Object.assign({}, headers);
|
|
831
|
+
delete this._subscriptions[id];
|
|
832
|
+
headers.id = id;
|
|
833
|
+
this._transmit({ command: 'UNSUBSCRIBE', headers });
|
|
834
|
+
}
|
|
835
|
+
begin(transactionId) {
|
|
836
|
+
const txId = transactionId || `tx-${this._counter++}`;
|
|
837
|
+
this._transmit({
|
|
838
|
+
command: 'BEGIN',
|
|
839
|
+
headers: {
|
|
840
|
+
transaction: txId,
|
|
841
|
+
},
|
|
842
|
+
});
|
|
843
|
+
const client = this;
|
|
844
|
+
return {
|
|
845
|
+
id: txId,
|
|
846
|
+
commit() {
|
|
847
|
+
client.commit(txId);
|
|
848
|
+
},
|
|
849
|
+
abort() {
|
|
850
|
+
client.abort(txId);
|
|
851
|
+
},
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
commit(transactionId) {
|
|
855
|
+
this._transmit({
|
|
856
|
+
command: 'COMMIT',
|
|
857
|
+
headers: {
|
|
858
|
+
transaction: transactionId,
|
|
859
|
+
},
|
|
860
|
+
});
|
|
861
|
+
}
|
|
862
|
+
abort(transactionId) {
|
|
863
|
+
this._transmit({
|
|
864
|
+
command: 'ABORT',
|
|
865
|
+
headers: {
|
|
866
|
+
transaction: transactionId,
|
|
867
|
+
},
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
ack(messageId, subscriptionId, headers = {}) {
|
|
871
|
+
headers = Object.assign({}, headers);
|
|
872
|
+
if (this._connectedVersion === Versions.V1_2) {
|
|
873
|
+
headers.id = messageId;
|
|
874
|
+
}
|
|
875
|
+
else {
|
|
876
|
+
headers['message-id'] = messageId;
|
|
877
|
+
}
|
|
878
|
+
headers.subscription = subscriptionId;
|
|
879
|
+
this._transmit({ command: 'ACK', headers });
|
|
880
|
+
}
|
|
881
|
+
nack(messageId, subscriptionId, headers = {}) {
|
|
882
|
+
headers = Object.assign({}, headers);
|
|
883
|
+
if (this._connectedVersion === Versions.V1_2) {
|
|
884
|
+
headers.id = messageId;
|
|
885
|
+
}
|
|
886
|
+
else {
|
|
887
|
+
headers['message-id'] = messageId;
|
|
888
|
+
}
|
|
889
|
+
headers.subscription = subscriptionId;
|
|
890
|
+
return this._transmit({ command: 'NACK', headers });
|
|
1102
891
|
}
|
|
1103
|
-
return new _compat_client__WEBPACK_IMPORTED_MODULE_1__["CompatClient"](wsFn);
|
|
1104
892
|
}
|
|
1105
|
-
}
|
|
1106
|
-
/**
|
|
1107
|
-
* In case you need to use a non standard class for WebSocket.
|
|
1108
|
-
*
|
|
1109
|
-
* For example when using within NodeJS environment:
|
|
1110
|
-
*
|
|
1111
|
-
* ```javascript
|
|
1112
|
-
* StompJs = require('../../esm5/');
|
|
1113
|
-
* Stomp = StompJs.Stomp;
|
|
1114
|
-
* Stomp.WebSocketClass = require('websocket').w3cwebsocket;
|
|
1115
|
-
* ```
|
|
1116
|
-
*
|
|
1117
|
-
* **Deprecated**
|
|
1118
|
-
*
|
|
1119
|
-
*
|
|
1120
|
-
* It will be removed in next major version. Please switch to {@link Client}
|
|
1121
|
-
* using [Client#webSocketFactory]{@link Client#webSocketFactory}.
|
|
1122
|
-
*/
|
|
1123
|
-
// tslint:disable-next-line:variable-name
|
|
1124
|
-
Stomp.WebSocketClass = null;
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
/***/ }),
|
|
1128
|
-
|
|
1129
|
-
/***/ "./src/frame-impl.ts":
|
|
1130
|
-
/*!***************************!*\
|
|
1131
|
-
!*** ./src/frame-impl.ts ***!
|
|
1132
|
-
\***************************/
|
|
1133
|
-
/*! exports provided: FrameImpl */
|
|
1134
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1135
893
|
|
|
1136
|
-
"use strict";
|
|
1137
|
-
__webpack_require__.r(__webpack_exports__);
|
|
1138
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FrameImpl", function() { return FrameImpl; });
|
|
1139
|
-
/* harmony import */ var _byte__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./byte */ "./src/byte.ts");
|
|
1140
|
-
|
|
1141
|
-
/**
|
|
1142
|
-
* Frame class represents a STOMP frame.
|
|
1143
|
-
*
|
|
1144
|
-
* @internal
|
|
1145
|
-
*/
|
|
1146
|
-
class FrameImpl {
|
|
1147
894
|
/**
|
|
1148
|
-
*
|
|
895
|
+
* STOMP Client Class.
|
|
1149
896
|
*
|
|
1150
|
-
*
|
|
1151
|
-
*/
|
|
1152
|
-
constructor(params) {
|
|
1153
|
-
const { command, headers, body, binaryBody, escapeHeaderValues, skipContentLengthHeader, } = params;
|
|
1154
|
-
this.command = command;
|
|
1155
|
-
this.headers = Object.assign({}, headers || {});
|
|
1156
|
-
if (binaryBody) {
|
|
1157
|
-
this._binaryBody = binaryBody;
|
|
1158
|
-
this.isBinaryBody = true;
|
|
1159
|
-
}
|
|
1160
|
-
else {
|
|
1161
|
-
this._body = body || '';
|
|
1162
|
-
this.isBinaryBody = false;
|
|
1163
|
-
}
|
|
1164
|
-
this.escapeHeaderValues = escapeHeaderValues || false;
|
|
1165
|
-
this.skipContentLengthHeader = skipContentLengthHeader || false;
|
|
1166
|
-
}
|
|
1167
|
-
/**
|
|
1168
|
-
* body of the frame
|
|
897
|
+
* Part of `@stomp/stompjs`.
|
|
1169
898
|
*/
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
899
|
+
class Client {
|
|
900
|
+
/**
|
|
901
|
+
* Create an instance.
|
|
902
|
+
*/
|
|
903
|
+
constructor(conf = {}) {
|
|
904
|
+
/**
|
|
905
|
+
* STOMP versions to attempt during STOMP handshake. By default versions `1.0`, `1.1`, and `1.2` are attempted.
|
|
906
|
+
*
|
|
907
|
+
* Example:
|
|
908
|
+
* ```javascript
|
|
909
|
+
* // Try only versions 1.0 and 1.1
|
|
910
|
+
* client.stompVersions = new Versions(['1.0', '1.1'])
|
|
911
|
+
* ```
|
|
912
|
+
*/
|
|
913
|
+
this.stompVersions = Versions.default;
|
|
914
|
+
/**
|
|
915
|
+
* Will retry if Stomp connection is not established in specified milliseconds.
|
|
916
|
+
* Default 0, which implies wait for ever.
|
|
917
|
+
*/
|
|
918
|
+
this.connectionTimeout = 0;
|
|
919
|
+
/**
|
|
920
|
+
* automatically reconnect with delay in milliseconds, set to 0 to disable.
|
|
921
|
+
*/
|
|
922
|
+
this.reconnectDelay = 5000;
|
|
923
|
+
/**
|
|
924
|
+
* Incoming heartbeat interval in milliseconds. Set to 0 to disable.
|
|
925
|
+
*/
|
|
926
|
+
this.heartbeatIncoming = 10000;
|
|
927
|
+
/**
|
|
928
|
+
* Outgoing heartbeat interval in milliseconds. Set to 0 to disable.
|
|
929
|
+
*/
|
|
930
|
+
this.heartbeatOutgoing = 10000;
|
|
931
|
+
/**
|
|
932
|
+
* This switches on a non standard behavior while sending WebSocket packets.
|
|
933
|
+
* It splits larger (text) packets into chunks of [maxWebSocketChunkSize]{@link Client#maxWebSocketChunkSize}.
|
|
934
|
+
* Only Java Spring brokers seems to use this mode.
|
|
935
|
+
*
|
|
936
|
+
* WebSockets, by itself, split large (text) packets,
|
|
937
|
+
* so it is not needed with a truly compliant STOMP/WebSocket broker.
|
|
938
|
+
* Actually setting it for such broker will cause large messages to fail.
|
|
939
|
+
*
|
|
940
|
+
* `false` by default.
|
|
941
|
+
*
|
|
942
|
+
* Binary frames are never split.
|
|
943
|
+
*/
|
|
944
|
+
this.splitLargeFrames = false;
|
|
945
|
+
/**
|
|
946
|
+
* See [splitLargeFrames]{@link Client#splitLargeFrames}.
|
|
947
|
+
* This has no effect if [splitLargeFrames]{@link Client#splitLargeFrames} is `false`.
|
|
948
|
+
*/
|
|
949
|
+
this.maxWebSocketChunkSize = 8 * 1024;
|
|
950
|
+
/**
|
|
951
|
+
* Usually the
|
|
952
|
+
* [type of WebSocket frame]{@link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send#Parameters}
|
|
953
|
+
* is automatically decided by type of the payload.
|
|
954
|
+
* Default is `false`, which should work with all compliant brokers.
|
|
955
|
+
*
|
|
956
|
+
* Set this flag to force binary frames.
|
|
957
|
+
*/
|
|
958
|
+
this.forceBinaryWSFrames = false;
|
|
959
|
+
/**
|
|
960
|
+
* A bug in ReactNative chops a string on occurrence of a NULL.
|
|
961
|
+
* See issue [https://github.com/stomp-js/stompjs/issues/89]{@link https://github.com/stomp-js/stompjs/issues/89}.
|
|
962
|
+
* This makes incoming WebSocket messages invalid STOMP packets.
|
|
963
|
+
* Setting this flag attempts to reverse the damage by appending a NULL.
|
|
964
|
+
* If the broker splits a large message into multiple WebSocket messages,
|
|
965
|
+
* this flag will cause data loss and abnormal termination of connection.
|
|
966
|
+
*
|
|
967
|
+
* This is not an ideal solution, but a stop gap until the underlying issue is fixed at ReactNative library.
|
|
968
|
+
*/
|
|
969
|
+
this.appendMissingNULLonIncoming = false;
|
|
970
|
+
/**
|
|
971
|
+
* Browsers do not immediately close WebSockets when `.close` is issued.
|
|
972
|
+
* This may cause reconnection to take a longer on certain type of failures.
|
|
973
|
+
* In case of incoming heartbeat failure, this experimental flag instructs the library
|
|
974
|
+
* to discard the socket immediately (even before it is actually closed).
|
|
975
|
+
*/
|
|
976
|
+
this.discardWebsocketOnCommFailure = false;
|
|
977
|
+
/**
|
|
978
|
+
* Activation state.
|
|
979
|
+
*
|
|
980
|
+
* It will usually be ACTIVE or INACTIVE.
|
|
981
|
+
* When deactivating it may go from ACTIVE to INACTIVE without entering DEACTIVATING.
|
|
982
|
+
*/
|
|
983
|
+
this.state = exports.ActivationState.INACTIVE;
|
|
984
|
+
// Dummy callbacks
|
|
985
|
+
const noOp = () => { };
|
|
986
|
+
this.debug = noOp;
|
|
987
|
+
this.beforeConnect = noOp;
|
|
988
|
+
this.onConnect = noOp;
|
|
989
|
+
this.onDisconnect = noOp;
|
|
990
|
+
this.onUnhandledMessage = noOp;
|
|
991
|
+
this.onUnhandledReceipt = noOp;
|
|
992
|
+
this.onUnhandledFrame = noOp;
|
|
993
|
+
this.onStompError = noOp;
|
|
994
|
+
this.onWebSocketClose = noOp;
|
|
995
|
+
this.onWebSocketError = noOp;
|
|
996
|
+
this.logRawCommunication = false;
|
|
997
|
+
this.onChangeState = noOp;
|
|
998
|
+
// These parameters would typically get proper values before connect is called
|
|
999
|
+
this.connectHeaders = {};
|
|
1000
|
+
this._disconnectHeaders = {};
|
|
1001
|
+
// Apply configuration
|
|
1002
|
+
this.configure(conf);
|
|
1173
1003
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
get binaryBody() {
|
|
1180
|
-
if (!this._binaryBody && !this.isBinaryBody) {
|
|
1181
|
-
this._binaryBody = new TextEncoder().encode(this._body);
|
|
1004
|
+
/**
|
|
1005
|
+
* Underlying WebSocket instance, READONLY.
|
|
1006
|
+
*/
|
|
1007
|
+
get webSocket() {
|
|
1008
|
+
return this._stompHandler?._webSocket;
|
|
1182
1009
|
}
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
for (const header of rawFrame.headers.reverse()) {
|
|
1195
|
-
const idx = header.indexOf(':');
|
|
1196
|
-
const key = trim(header[0]);
|
|
1197
|
-
let value = trim(header[1]);
|
|
1198
|
-
if (escapeHeaderValues &&
|
|
1199
|
-
rawFrame.command !== 'CONNECT' &&
|
|
1200
|
-
rawFrame.command !== 'CONNECTED') {
|
|
1201
|
-
value = FrameImpl.hdrValueUnEscape(value);
|
|
1202
|
-
}
|
|
1203
|
-
headers[key] = value;
|
|
1204
|
-
}
|
|
1205
|
-
return new FrameImpl({
|
|
1206
|
-
command: rawFrame.command,
|
|
1207
|
-
headers,
|
|
1208
|
-
binaryBody: rawFrame.binaryBody,
|
|
1209
|
-
escapeHeaderValues,
|
|
1210
|
-
});
|
|
1211
|
-
}
|
|
1212
|
-
/**
|
|
1213
|
-
* @internal
|
|
1214
|
-
*/
|
|
1215
|
-
toString() {
|
|
1216
|
-
return this.serializeCmdAndHeaders();
|
|
1217
|
-
}
|
|
1218
|
-
/**
|
|
1219
|
-
* serialize this Frame in a format suitable to be passed to WebSocket.
|
|
1220
|
-
* If the body is string the output will be string.
|
|
1221
|
-
* If the body is binary (i.e. of type Unit8Array) it will be serialized to ArrayBuffer.
|
|
1222
|
-
*
|
|
1223
|
-
* @internal
|
|
1224
|
-
*/
|
|
1225
|
-
serialize() {
|
|
1226
|
-
const cmdAndHeaders = this.serializeCmdAndHeaders();
|
|
1227
|
-
if (this.isBinaryBody) {
|
|
1228
|
-
return FrameImpl.toUnit8Array(cmdAndHeaders, this._binaryBody).buffer;
|
|
1010
|
+
/**
|
|
1011
|
+
* Disconnection headers.
|
|
1012
|
+
*/
|
|
1013
|
+
get disconnectHeaders() {
|
|
1014
|
+
return this._disconnectHeaders;
|
|
1015
|
+
}
|
|
1016
|
+
set disconnectHeaders(value) {
|
|
1017
|
+
this._disconnectHeaders = value;
|
|
1018
|
+
if (this._stompHandler) {
|
|
1019
|
+
this._stompHandler.disconnectHeaders = this._disconnectHeaders;
|
|
1020
|
+
}
|
|
1229
1021
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1022
|
+
/**
|
|
1023
|
+
* `true` if there is a active connection with STOMP Broker
|
|
1024
|
+
*/
|
|
1025
|
+
get connected() {
|
|
1026
|
+
return !!this._stompHandler && this._stompHandler.connected;
|
|
1232
1027
|
}
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1028
|
+
/**
|
|
1029
|
+
* version of STOMP protocol negotiated with the server, READONLY
|
|
1030
|
+
*/
|
|
1031
|
+
get connectedVersion() {
|
|
1032
|
+
return this._stompHandler ? this._stompHandler.connectedVersion : undefined;
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* if the client is active (connected or going to reconnect)
|
|
1036
|
+
*/
|
|
1037
|
+
get active() {
|
|
1038
|
+
return this.state === exports.ActivationState.ACTIVE;
|
|
1039
|
+
}
|
|
1040
|
+
_changeState(state) {
|
|
1041
|
+
this.state = state;
|
|
1042
|
+
this.onChangeState(state);
|
|
1043
|
+
}
|
|
1044
|
+
/**
|
|
1045
|
+
* Update configuration.
|
|
1046
|
+
*/
|
|
1047
|
+
configure(conf) {
|
|
1048
|
+
// bulk assign all properties to this
|
|
1049
|
+
Object.assign(this, conf);
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Initiate the connection with the broker.
|
|
1053
|
+
* If the connection breaks, as per [Client#reconnectDelay]{@link Client#reconnectDelay},
|
|
1054
|
+
* it will keep trying to reconnect.
|
|
1055
|
+
*
|
|
1056
|
+
* Call [Client#deactivate]{@link Client#deactivate} to disconnect and stop reconnection attempts.
|
|
1057
|
+
*/
|
|
1058
|
+
activate() {
|
|
1059
|
+
if (this.state === exports.ActivationState.DEACTIVATING) {
|
|
1060
|
+
this.debug('Still DEACTIVATING, please await call to deactivate before trying to re-activate');
|
|
1061
|
+
throw new Error('Still DEACTIVATING, can not activate now');
|
|
1062
|
+
}
|
|
1063
|
+
if (this.active) {
|
|
1064
|
+
this.debug('Already ACTIVE, ignoring request to activate');
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
this._changeState(exports.ActivationState.ACTIVE);
|
|
1068
|
+
this._connect();
|
|
1069
|
+
}
|
|
1070
|
+
async _connect() {
|
|
1071
|
+
if (this.connected) {
|
|
1072
|
+
this.debug('STOMP: already connected, nothing to do');
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
await this.beforeConnect();
|
|
1076
|
+
if (!this.active) {
|
|
1077
|
+
this.debug('Client has been marked inactive, will not attempt to connect');
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
// setup connection watcher
|
|
1081
|
+
if (this.connectionTimeout > 0) {
|
|
1082
|
+
// clear first
|
|
1083
|
+
if (this._connectionWatcher) {
|
|
1084
|
+
clearTimeout(this._connectionWatcher);
|
|
1085
|
+
}
|
|
1086
|
+
this._connectionWatcher = setTimeout(() => {
|
|
1087
|
+
if (this.connected) {
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1090
|
+
// Connection not established, close the underlying socket
|
|
1091
|
+
// a reconnection will be attempted
|
|
1092
|
+
this.debug(`Connection not established in ${this.connectionTimeout}ms, closing socket`);
|
|
1093
|
+
this.forceDisconnect();
|
|
1094
|
+
}, this.connectionTimeout);
|
|
1095
|
+
}
|
|
1096
|
+
this.debug('Opening Web Socket...');
|
|
1097
|
+
// Get the actual WebSocket (or a similar object)
|
|
1098
|
+
const webSocket = this._createWebSocket();
|
|
1099
|
+
this._stompHandler = new StompHandler(this, webSocket, {
|
|
1100
|
+
debug: this.debug,
|
|
1101
|
+
stompVersions: this.stompVersions,
|
|
1102
|
+
connectHeaders: this.connectHeaders,
|
|
1103
|
+
disconnectHeaders: this._disconnectHeaders,
|
|
1104
|
+
heartbeatIncoming: this.heartbeatIncoming,
|
|
1105
|
+
heartbeatOutgoing: this.heartbeatOutgoing,
|
|
1106
|
+
splitLargeFrames: this.splitLargeFrames,
|
|
1107
|
+
maxWebSocketChunkSize: this.maxWebSocketChunkSize,
|
|
1108
|
+
forceBinaryWSFrames: this.forceBinaryWSFrames,
|
|
1109
|
+
logRawCommunication: this.logRawCommunication,
|
|
1110
|
+
appendMissingNULLonIncoming: this.appendMissingNULLonIncoming,
|
|
1111
|
+
discardWebsocketOnCommFailure: this.discardWebsocketOnCommFailure,
|
|
1112
|
+
onConnect: frame => {
|
|
1113
|
+
// Successfully connected, stop the connection watcher
|
|
1114
|
+
if (this._connectionWatcher) {
|
|
1115
|
+
clearTimeout(this._connectionWatcher);
|
|
1116
|
+
this._connectionWatcher = undefined;
|
|
1117
|
+
}
|
|
1118
|
+
if (!this.active) {
|
|
1119
|
+
this.debug('STOMP got connected while deactivate was issued, will disconnect now');
|
|
1120
|
+
this._disposeStompHandler();
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
this.onConnect(frame);
|
|
1124
|
+
},
|
|
1125
|
+
onDisconnect: frame => {
|
|
1126
|
+
this.onDisconnect(frame);
|
|
1127
|
+
},
|
|
1128
|
+
onStompError: frame => {
|
|
1129
|
+
this.onStompError(frame);
|
|
1130
|
+
},
|
|
1131
|
+
onWebSocketClose: evt => {
|
|
1132
|
+
this._stompHandler = undefined; // a new one will be created in case of a reconnect
|
|
1133
|
+
if (this.state === exports.ActivationState.DEACTIVATING) {
|
|
1134
|
+
// Mark deactivation complete
|
|
1135
|
+
this._changeState(exports.ActivationState.INACTIVE);
|
|
1136
|
+
}
|
|
1137
|
+
// The callback is called before attempting to reconnect, this would allow the client
|
|
1138
|
+
// to be `deactivated` in the callback.
|
|
1139
|
+
this.onWebSocketClose(evt);
|
|
1140
|
+
if (this.active) {
|
|
1141
|
+
this._schedule_reconnect();
|
|
1142
|
+
}
|
|
1143
|
+
},
|
|
1144
|
+
onWebSocketError: evt => {
|
|
1145
|
+
this.onWebSocketError(evt);
|
|
1146
|
+
},
|
|
1147
|
+
onUnhandledMessage: message => {
|
|
1148
|
+
this.onUnhandledMessage(message);
|
|
1149
|
+
},
|
|
1150
|
+
onUnhandledReceipt: frame => {
|
|
1151
|
+
this.onUnhandledReceipt(frame);
|
|
1152
|
+
},
|
|
1153
|
+
onUnhandledFrame: frame => {
|
|
1154
|
+
this.onUnhandledFrame(frame);
|
|
1155
|
+
},
|
|
1156
|
+
});
|
|
1157
|
+
this._stompHandler.start();
|
|
1158
|
+
}
|
|
1159
|
+
_createWebSocket() {
|
|
1160
|
+
let webSocket;
|
|
1161
|
+
if (this.webSocketFactory) {
|
|
1162
|
+
webSocket = this.webSocketFactory();
|
|
1163
|
+
}
|
|
1164
|
+
else if (this.brokerURL) {
|
|
1165
|
+
webSocket = new WebSocket(this.brokerURL, this.stompVersions.protocolVersions());
|
|
1245
1166
|
}
|
|
1246
1167
|
else {
|
|
1247
|
-
|
|
1168
|
+
throw new Error('Either brokerURL or webSocketFactory must be provided');
|
|
1169
|
+
}
|
|
1170
|
+
webSocket.binaryType = 'arraybuffer';
|
|
1171
|
+
return webSocket;
|
|
1172
|
+
}
|
|
1173
|
+
_schedule_reconnect() {
|
|
1174
|
+
if (this.reconnectDelay > 0) {
|
|
1175
|
+
this.debug(`STOMP: scheduling reconnection in ${this.reconnectDelay}ms`);
|
|
1176
|
+
this._reconnector = setTimeout(() => {
|
|
1177
|
+
this._connect();
|
|
1178
|
+
}, this.reconnectDelay);
|
|
1248
1179
|
}
|
|
1249
1180
|
}
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1181
|
+
/**
|
|
1182
|
+
* Disconnect if connected and stop auto reconnect loop.
|
|
1183
|
+
* Appropriate callbacks will be invoked if there is an underlying STOMP connection.
|
|
1184
|
+
*
|
|
1185
|
+
* This call is async. It will resolve immediately if there is no underlying active websocket,
|
|
1186
|
+
* otherwise, it will resolve after the underlying websocket is properly disposed of.
|
|
1187
|
+
*
|
|
1188
|
+
* It is not an error to invoke this method more than once.
|
|
1189
|
+
* Each of those would resolve on completion of deactivation.
|
|
1190
|
+
*
|
|
1191
|
+
* To reactivate, you can call [Client#activate]{@link Client#activate}.
|
|
1192
|
+
*
|
|
1193
|
+
* Experimental: pass `force: true` to immediately discard the underlying connection.
|
|
1194
|
+
* This mode will skip both the STOMP and the Websocket shutdown sequences.
|
|
1195
|
+
* In some cases, browsers take a long time in the Websocket shutdown if the underlying connection had gone stale.
|
|
1196
|
+
* Using this mode can speed up.
|
|
1197
|
+
* When this mode is used, the actual Websocket may linger for a while
|
|
1198
|
+
* and the broker may not realize that the connection is no longer in use.
|
|
1199
|
+
*
|
|
1200
|
+
* It is possible to invoke this method initially without the `force` option
|
|
1201
|
+
* and subsequently, say after a wait, with the `force` option.
|
|
1202
|
+
*/
|
|
1203
|
+
async deactivate(options = {}) {
|
|
1204
|
+
const force = options.force || false;
|
|
1205
|
+
const needToDispose = this.active;
|
|
1206
|
+
let retPromise;
|
|
1207
|
+
if (this.state === exports.ActivationState.INACTIVE) {
|
|
1208
|
+
this.debug(`Already INACTIVE, nothing more to do`);
|
|
1209
|
+
return Promise.resolve();
|
|
1210
|
+
}
|
|
1211
|
+
this._changeState(exports.ActivationState.DEACTIVATING);
|
|
1212
|
+
// Clear if a reconnection was scheduled
|
|
1213
|
+
if (this._reconnector) {
|
|
1214
|
+
clearTimeout(this._reconnector);
|
|
1215
|
+
this._reconnector = undefined;
|
|
1216
|
+
}
|
|
1217
|
+
if (this._stompHandler &&
|
|
1218
|
+
// @ts-ignore - if there is a _stompHandler, there is the webSocket
|
|
1219
|
+
this.webSocket.readyState !== exports.StompSocketState.CLOSED) {
|
|
1220
|
+
const origOnWebSocketClose = this._stompHandler.onWebSocketClose;
|
|
1221
|
+
// we need to wait for the underlying websocket to close
|
|
1222
|
+
retPromise = new Promise((resolve, reject) => {
|
|
1223
|
+
// @ts-ignore - there is a _stompHandler
|
|
1224
|
+
this._stompHandler.onWebSocketClose = evt => {
|
|
1225
|
+
origOnWebSocketClose(evt);
|
|
1226
|
+
resolve();
|
|
1227
|
+
};
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
else {
|
|
1231
|
+
// indicate that auto reconnect loop should terminate
|
|
1232
|
+
this._changeState(exports.ActivationState.INACTIVE);
|
|
1233
|
+
return Promise.resolve();
|
|
1234
|
+
}
|
|
1235
|
+
if (force) {
|
|
1236
|
+
this._stompHandler?.discardWebsocket();
|
|
1237
|
+
}
|
|
1238
|
+
else if (needToDispose) {
|
|
1239
|
+
this._disposeStompHandler();
|
|
1240
|
+
}
|
|
1241
|
+
return retPromise;
|
|
1242
|
+
}
|
|
1243
|
+
/**
|
|
1244
|
+
* Force disconnect if there is an active connection by directly closing the underlying WebSocket.
|
|
1245
|
+
* This is different than a normal disconnect where a DISCONNECT sequence is carried out with the broker.
|
|
1246
|
+
* After forcing disconnect, automatic reconnect will be attempted.
|
|
1247
|
+
* To stop further reconnects call [Client#deactivate]{@link Client#deactivate} as well.
|
|
1248
|
+
*/
|
|
1249
|
+
forceDisconnect() {
|
|
1250
|
+
if (this._stompHandler) {
|
|
1251
|
+
this._stompHandler.forceDisconnect();
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
_disposeStompHandler() {
|
|
1255
|
+
// Dispose STOMP Handler
|
|
1256
|
+
if (this._stompHandler) {
|
|
1257
|
+
this._stompHandler.dispose();
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Send a message to a named destination. Refer to your STOMP broker documentation for types
|
|
1262
|
+
* and naming of destinations.
|
|
1263
|
+
*
|
|
1264
|
+
* STOMP protocol specifies and suggests some headers and also allows broker specific headers.
|
|
1265
|
+
*
|
|
1266
|
+
* `body` must be String.
|
|
1267
|
+
* You will need to covert the payload to string in case it is not string (e.g. JSON).
|
|
1268
|
+
*
|
|
1269
|
+
* To send a binary message body use binaryBody parameter. It should be a
|
|
1270
|
+
* [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array).
|
|
1271
|
+
* Sometimes brokers may not support binary frames out of the box.
|
|
1272
|
+
* Please check your broker documentation.
|
|
1273
|
+
*
|
|
1274
|
+
* `content-length` header is automatically added to the STOMP Frame sent to the broker.
|
|
1275
|
+
* Set `skipContentLengthHeader` to indicate that `content-length` header should not be added.
|
|
1276
|
+
* For binary messages `content-length` header is always added.
|
|
1277
|
+
*
|
|
1278
|
+
* Caution: The broker will, most likely, report an error and disconnect if message body has NULL octet(s)
|
|
1279
|
+
* and `content-length` header is missing.
|
|
1280
|
+
*
|
|
1281
|
+
* ```javascript
|
|
1282
|
+
* client.publish({destination: "/queue/test", headers: {priority: 9}, body: "Hello, STOMP"});
|
|
1283
|
+
*
|
|
1284
|
+
* // Only destination is mandatory parameter
|
|
1285
|
+
* client.publish({destination: "/queue/test", body: "Hello, STOMP"});
|
|
1286
|
+
*
|
|
1287
|
+
* // Skip content-length header in the frame to the broker
|
|
1288
|
+
* client.publish({"/queue/test", body: "Hello, STOMP", skipContentLengthHeader: true});
|
|
1289
|
+
*
|
|
1290
|
+
* var binaryData = generateBinaryData(); // This need to be of type Uint8Array
|
|
1291
|
+
* // setting content-type header is not mandatory, however a good practice
|
|
1292
|
+
* client.publish({destination: '/topic/special', binaryBody: binaryData,
|
|
1293
|
+
* headers: {'content-type': 'application/octet-stream'}});
|
|
1294
|
+
* ```
|
|
1295
|
+
*/
|
|
1296
|
+
publish(params) {
|
|
1297
|
+
this._checkConnection();
|
|
1298
|
+
// @ts-ignore - we already checked that there is a _stompHandler, and it is connected
|
|
1299
|
+
this._stompHandler.publish(params);
|
|
1300
|
+
}
|
|
1301
|
+
_checkConnection() {
|
|
1302
|
+
if (!this.connected) {
|
|
1303
|
+
throw new TypeError('There is no underlying STOMP connection');
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
/**
|
|
1307
|
+
* STOMP brokers may carry out operation asynchronously and allow requesting for acknowledgement.
|
|
1308
|
+
* To request an acknowledgement, a `receipt` header needs to be sent with the actual request.
|
|
1309
|
+
* The value (say receipt-id) for this header needs to be unique for each use. Typically a sequence, a UUID, a
|
|
1310
|
+
* random number or a combination may be used.
|
|
1311
|
+
*
|
|
1312
|
+
* A complaint broker will send a RECEIPT frame when an operation has actually been completed.
|
|
1313
|
+
* The operation needs to be matched based in the value of the receipt-id.
|
|
1314
|
+
*
|
|
1315
|
+
* This method allow watching for a receipt and invoke the callback
|
|
1316
|
+
* when corresponding receipt has been received.
|
|
1317
|
+
*
|
|
1318
|
+
* The actual {@link FrameImpl} will be passed as parameter to the callback.
|
|
1319
|
+
*
|
|
1320
|
+
* Example:
|
|
1321
|
+
* ```javascript
|
|
1322
|
+
* // Subscribing with acknowledgement
|
|
1323
|
+
* let receiptId = randomText();
|
|
1324
|
+
*
|
|
1325
|
+
* client.watchForReceipt(receiptId, function() {
|
|
1326
|
+
* // Will be called after server acknowledges
|
|
1327
|
+
* });
|
|
1328
|
+
*
|
|
1329
|
+
* client.subscribe(TEST.destination, onMessage, {receipt: receiptId});
|
|
1330
|
+
*
|
|
1331
|
+
*
|
|
1332
|
+
* // Publishing with acknowledgement
|
|
1333
|
+
* receiptId = randomText();
|
|
1334
|
+
*
|
|
1335
|
+
* client.watchForReceipt(receiptId, function() {
|
|
1336
|
+
* // Will be called after server acknowledges
|
|
1337
|
+
* });
|
|
1338
|
+
* client.publish({destination: TEST.destination, headers: {receipt: receiptId}, body: msg});
|
|
1339
|
+
* ```
|
|
1340
|
+
*/
|
|
1341
|
+
watchForReceipt(receiptId, callback) {
|
|
1342
|
+
this._checkConnection();
|
|
1343
|
+
// @ts-ignore - we already checked that there is a _stompHandler, and it is connected
|
|
1344
|
+
this._stompHandler.watchForReceipt(receiptId, callback);
|
|
1345
|
+
}
|
|
1346
|
+
/**
|
|
1347
|
+
* Subscribe to a STOMP Broker location. The callback will be invoked for each received message with
|
|
1348
|
+
* the {@link IMessage} as argument.
|
|
1349
|
+
*
|
|
1350
|
+
* Note: The library will generate an unique ID if there is none provided in the headers.
|
|
1351
|
+
* To use your own ID, pass it using the headers argument.
|
|
1352
|
+
*
|
|
1353
|
+
* ```javascript
|
|
1354
|
+
* callback = function(message) {
|
|
1355
|
+
* // called when the client receives a STOMP message from the server
|
|
1356
|
+
* if (message.body) {
|
|
1357
|
+
* alert("got message with body " + message.body)
|
|
1358
|
+
* } else {
|
|
1359
|
+
* alert("got empty message");
|
|
1360
|
+
* }
|
|
1361
|
+
* });
|
|
1362
|
+
*
|
|
1363
|
+
* var subscription = client.subscribe("/queue/test", callback);
|
|
1364
|
+
*
|
|
1365
|
+
* // Explicit subscription id
|
|
1366
|
+
* var mySubId = 'my-subscription-id-001';
|
|
1367
|
+
* var subscription = client.subscribe(destination, callback, { id: mySubId });
|
|
1368
|
+
* ```
|
|
1369
|
+
*/
|
|
1370
|
+
subscribe(destination, callback, headers = {}) {
|
|
1371
|
+
this._checkConnection();
|
|
1372
|
+
// @ts-ignore - we already checked that there is a _stompHandler, and it is connected
|
|
1373
|
+
return this._stompHandler.subscribe(destination, callback, headers);
|
|
1374
|
+
}
|
|
1375
|
+
/**
|
|
1376
|
+
* It is preferable to unsubscribe from a subscription by calling
|
|
1377
|
+
* `unsubscribe()` directly on {@link StompSubscription} returned by `client.subscribe()`:
|
|
1378
|
+
*
|
|
1379
|
+
* ```javascript
|
|
1380
|
+
* var subscription = client.subscribe(destination, onmessage);
|
|
1381
|
+
* // ...
|
|
1382
|
+
* subscription.unsubscribe();
|
|
1383
|
+
* ```
|
|
1384
|
+
*
|
|
1385
|
+
* See: http://stomp.github.com/stomp-specification-1.2.html#UNSUBSCRIBE UNSUBSCRIBE Frame
|
|
1386
|
+
*/
|
|
1387
|
+
unsubscribe(id, headers = {}) {
|
|
1388
|
+
this._checkConnection();
|
|
1389
|
+
// @ts-ignore - we already checked that there is a _stompHandler, and it is connected
|
|
1390
|
+
this._stompHandler.unsubscribe(id, headers);
|
|
1391
|
+
}
|
|
1392
|
+
/**
|
|
1393
|
+
* Start a transaction, the returned {@link ITransaction} has methods - [commit]{@link ITransaction#commit}
|
|
1394
|
+
* and [abort]{@link ITransaction#abort}.
|
|
1395
|
+
*
|
|
1396
|
+
* `transactionId` is optional, if not passed the library will generate it internally.
|
|
1397
|
+
*/
|
|
1398
|
+
begin(transactionId) {
|
|
1399
|
+
this._checkConnection();
|
|
1400
|
+
// @ts-ignore - we already checked that there is a _stompHandler, and it is connected
|
|
1401
|
+
return this._stompHandler.begin(transactionId);
|
|
1402
|
+
}
|
|
1403
|
+
/**
|
|
1404
|
+
* Commit a transaction.
|
|
1405
|
+
*
|
|
1406
|
+
* It is preferable to commit a transaction by calling [commit]{@link ITransaction#commit} directly on
|
|
1407
|
+
* {@link ITransaction} returned by [client.begin]{@link Client#begin}.
|
|
1408
|
+
*
|
|
1409
|
+
* ```javascript
|
|
1410
|
+
* var tx = client.begin(txId);
|
|
1411
|
+
* //...
|
|
1412
|
+
* tx.commit();
|
|
1413
|
+
* ```
|
|
1414
|
+
*/
|
|
1415
|
+
commit(transactionId) {
|
|
1416
|
+
this._checkConnection();
|
|
1417
|
+
// @ts-ignore - we already checked that there is a _stompHandler, and it is connected
|
|
1418
|
+
this._stompHandler.commit(transactionId);
|
|
1419
|
+
}
|
|
1420
|
+
/**
|
|
1421
|
+
* Abort a transaction.
|
|
1422
|
+
* It is preferable to abort a transaction by calling [abort]{@link ITransaction#abort} directly on
|
|
1423
|
+
* {@link ITransaction} returned by [client.begin]{@link Client#begin}.
|
|
1424
|
+
*
|
|
1425
|
+
* ```javascript
|
|
1426
|
+
* var tx = client.begin(txId);
|
|
1427
|
+
* //...
|
|
1428
|
+
* tx.abort();
|
|
1429
|
+
* ```
|
|
1430
|
+
*/
|
|
1431
|
+
abort(transactionId) {
|
|
1432
|
+
this._checkConnection();
|
|
1433
|
+
// @ts-ignore - we already checked that there is a _stompHandler, and it is connected
|
|
1434
|
+
this._stompHandler.abort(transactionId);
|
|
1435
|
+
}
|
|
1436
|
+
/**
|
|
1437
|
+
* ACK a message. It is preferable to acknowledge a message by calling [ack]{@link IMessage#ack} directly
|
|
1438
|
+
* on the {@link IMessage} handled by a subscription callback:
|
|
1439
|
+
*
|
|
1440
|
+
* ```javascript
|
|
1441
|
+
* var callback = function (message) {
|
|
1442
|
+
* // process the message
|
|
1443
|
+
* // acknowledge it
|
|
1444
|
+
* message.ack();
|
|
1445
|
+
* };
|
|
1446
|
+
* client.subscribe(destination, callback, {'ack': 'client'});
|
|
1447
|
+
* ```
|
|
1448
|
+
*/
|
|
1449
|
+
ack(messageId, subscriptionId, headers = {}) {
|
|
1450
|
+
this._checkConnection();
|
|
1451
|
+
// @ts-ignore - we already checked that there is a _stompHandler, and it is connected
|
|
1452
|
+
this._stompHandler.ack(messageId, subscriptionId, headers);
|
|
1453
|
+
}
|
|
1454
|
+
/**
|
|
1455
|
+
* NACK a message. It is preferable to acknowledge a message by calling [nack]{@link IMessage#nack} directly
|
|
1456
|
+
* on the {@link IMessage} handled by a subscription callback:
|
|
1457
|
+
*
|
|
1458
|
+
* ```javascript
|
|
1459
|
+
* var callback = function (message) {
|
|
1460
|
+
* // process the message
|
|
1461
|
+
* // an error occurs, nack it
|
|
1462
|
+
* message.nack();
|
|
1463
|
+
* };
|
|
1464
|
+
* client.subscribe(destination, callback, {'ack': 'client'});
|
|
1465
|
+
* ```
|
|
1466
|
+
*/
|
|
1467
|
+
nack(messageId, subscriptionId, headers = {}) {
|
|
1468
|
+
this._checkConnection();
|
|
1469
|
+
// @ts-ignore - we already checked that there is a _stompHandler, and it is connected
|
|
1470
|
+
this._stompHandler.nack(messageId, subscriptionId, headers);
|
|
1253
1471
|
}
|
|
1254
|
-
return lines.join(_byte__WEBPACK_IMPORTED_MODULE_0__["BYTE"].LF) + _byte__WEBPACK_IMPORTED_MODULE_0__["BYTE"].LF + _byte__WEBPACK_IMPORTED_MODULE_0__["BYTE"].LF;
|
|
1255
|
-
}
|
|
1256
|
-
isBodyEmpty() {
|
|
1257
|
-
return this.bodyLength() === 0;
|
|
1258
|
-
}
|
|
1259
|
-
bodyLength() {
|
|
1260
|
-
const binaryBody = this.binaryBody;
|
|
1261
|
-
return binaryBody ? binaryBody.length : 0;
|
|
1262
|
-
}
|
|
1263
|
-
/**
|
|
1264
|
-
* Compute the size of a UTF-8 string by counting its number of bytes
|
|
1265
|
-
* (and not the number of characters composing the string)
|
|
1266
|
-
*/
|
|
1267
|
-
static sizeOfUTF8(s) {
|
|
1268
|
-
return s ? new TextEncoder().encode(s).length : 0;
|
|
1269
|
-
}
|
|
1270
|
-
static toUnit8Array(cmdAndHeaders, binaryBody) {
|
|
1271
|
-
const uint8CmdAndHeaders = new TextEncoder().encode(cmdAndHeaders);
|
|
1272
|
-
const nullTerminator = new Uint8Array([0]);
|
|
1273
|
-
const uint8Frame = new Uint8Array(uint8CmdAndHeaders.length + binaryBody.length + nullTerminator.length);
|
|
1274
|
-
uint8Frame.set(uint8CmdAndHeaders);
|
|
1275
|
-
uint8Frame.set(binaryBody, uint8CmdAndHeaders.length);
|
|
1276
|
-
uint8Frame.set(nullTerminator, uint8CmdAndHeaders.length + binaryBody.length);
|
|
1277
|
-
return uint8Frame;
|
|
1278
1472
|
}
|
|
1473
|
+
|
|
1279
1474
|
/**
|
|
1280
|
-
*
|
|
1475
|
+
* Configuration options for STOMP Client, each key corresponds to
|
|
1476
|
+
* field by the same name in {@link Client}. This can be passed to
|
|
1477
|
+
* the constructor of {@link Client} or to [Client#configure]{@link Client#configure}.
|
|
1281
1478
|
*
|
|
1282
|
-
*
|
|
1479
|
+
* There used to be a class with the same name in `@stomp/ng2-stompjs`, which has been replaced by
|
|
1480
|
+
* {@link RxStompConfig} and {@link InjectableRxStompConfig}.
|
|
1481
|
+
*
|
|
1482
|
+
* Part of `@stomp/stompjs`.
|
|
1283
1483
|
*/
|
|
1284
|
-
|
|
1285
|
-
const frame = new FrameImpl(params);
|
|
1286
|
-
return frame.serialize();
|
|
1484
|
+
class StompConfig {
|
|
1287
1485
|
}
|
|
1486
|
+
|
|
1288
1487
|
/**
|
|
1289
|
-
*
|
|
1488
|
+
* STOMP headers. Many functions calls will accept headers as parameters.
|
|
1489
|
+
* The headers sent by Broker will be available as [IFrame#headers]{@link IFrame#headers}.
|
|
1490
|
+
*
|
|
1491
|
+
* `key` and `value` must be valid strings.
|
|
1492
|
+
* In addition, `key` must not contain `CR`, `LF`, or `:`.
|
|
1493
|
+
*
|
|
1494
|
+
* Part of `@stomp/stompjs`.
|
|
1290
1495
|
*/
|
|
1291
|
-
|
|
1292
|
-
return str
|
|
1293
|
-
.replace(/\\/g, '\\\\')
|
|
1294
|
-
.replace(/\r/g, '\\r')
|
|
1295
|
-
.replace(/\n/g, '\\n')
|
|
1296
|
-
.replace(/:/g, '\\c');
|
|
1496
|
+
class StompHeaders {
|
|
1297
1497
|
}
|
|
1498
|
+
|
|
1298
1499
|
/**
|
|
1299
|
-
*
|
|
1500
|
+
* Part of `@stomp/stompjs`.
|
|
1501
|
+
*
|
|
1502
|
+
* @internal
|
|
1300
1503
|
*/
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
.
|
|
1304
|
-
.replace(/\\n/g, '\n')
|
|
1305
|
-
.replace(/\\c/g, ':')
|
|
1306
|
-
.replace(/\\\\/g, '\\');
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
/***/ }),
|
|
1312
|
-
|
|
1313
|
-
/***/ "./src/index.ts":
|
|
1314
|
-
/*!**********************!*\
|
|
1315
|
-
!*** ./src/index.ts ***!
|
|
1316
|
-
\**********************/
|
|
1317
|
-
/*! exports provided: Client, FrameImpl, Parser, StompConfig, StompHeaders, StompSubscription, StompSocketState, ActivationState, Versions, CompatClient, Stomp */
|
|
1318
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1319
|
-
|
|
1320
|
-
"use strict";
|
|
1321
|
-
__webpack_require__.r(__webpack_exports__);
|
|
1322
|
-
/* harmony import */ var _client__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./client */ "./src/client.ts");
|
|
1323
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Client", function() { return _client__WEBPACK_IMPORTED_MODULE_0__["Client"]; });
|
|
1324
|
-
|
|
1325
|
-
/* harmony import */ var _frame_impl__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./frame-impl */ "./src/frame-impl.ts");
|
|
1326
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "FrameImpl", function() { return _frame_impl__WEBPACK_IMPORTED_MODULE_1__["FrameImpl"]; });
|
|
1327
|
-
|
|
1328
|
-
/* harmony import */ var _parser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./parser */ "./src/parser.ts");
|
|
1329
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Parser", function() { return _parser__WEBPACK_IMPORTED_MODULE_2__["Parser"]; });
|
|
1330
|
-
|
|
1331
|
-
/* harmony import */ var _stomp_config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stomp-config */ "./src/stomp-config.ts");
|
|
1332
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "StompConfig", function() { return _stomp_config__WEBPACK_IMPORTED_MODULE_3__["StompConfig"]; });
|
|
1333
|
-
|
|
1334
|
-
/* harmony import */ var _stomp_headers__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./stomp-headers */ "./src/stomp-headers.ts");
|
|
1335
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "StompHeaders", function() { return _stomp_headers__WEBPACK_IMPORTED_MODULE_4__["StompHeaders"]; });
|
|
1336
|
-
|
|
1337
|
-
/* harmony import */ var _stomp_subscription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./stomp-subscription */ "./src/stomp-subscription.ts");
|
|
1338
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "StompSubscription", function() { return _stomp_subscription__WEBPACK_IMPORTED_MODULE_5__["StompSubscription"]; });
|
|
1339
|
-
|
|
1340
|
-
/* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./types */ "./src/types.ts");
|
|
1341
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "StompSocketState", function() { return _types__WEBPACK_IMPORTED_MODULE_6__["StompSocketState"]; });
|
|
1342
|
-
|
|
1343
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ActivationState", function() { return _types__WEBPACK_IMPORTED_MODULE_6__["ActivationState"]; });
|
|
1344
|
-
|
|
1345
|
-
/* harmony import */ var _versions__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./versions */ "./src/versions.ts");
|
|
1346
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Versions", function() { return _versions__WEBPACK_IMPORTED_MODULE_7__["Versions"]; });
|
|
1347
|
-
|
|
1348
|
-
/* harmony import */ var _compatibility_compat_client__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./compatibility/compat-client */ "./src/compatibility/compat-client.ts");
|
|
1349
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "CompatClient", function() { return _compatibility_compat_client__WEBPACK_IMPORTED_MODULE_8__["CompatClient"]; });
|
|
1350
|
-
|
|
1351
|
-
/* harmony import */ var _compatibility_stomp__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./compatibility/stomp */ "./src/compatibility/stomp.ts");
|
|
1352
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Stomp", function() { return _compatibility_stomp__WEBPACK_IMPORTED_MODULE_9__["Stomp"]; });
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
// Compatibility code
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
/***/ }),
|
|
1368
|
-
|
|
1369
|
-
/***/ "./src/parser.ts":
|
|
1370
|
-
/*!***********************!*\
|
|
1371
|
-
!*** ./src/parser.ts ***!
|
|
1372
|
-
\***********************/
|
|
1373
|
-
/*! exports provided: Parser */
|
|
1374
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1375
|
-
|
|
1376
|
-
"use strict";
|
|
1377
|
-
__webpack_require__.r(__webpack_exports__);
|
|
1378
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Parser", function() { return Parser; });
|
|
1379
|
-
/**
|
|
1380
|
-
* @internal
|
|
1381
|
-
*/
|
|
1382
|
-
const NULL = 0;
|
|
1383
|
-
/**
|
|
1384
|
-
* @internal
|
|
1385
|
-
*/
|
|
1386
|
-
const LF = 10;
|
|
1387
|
-
/**
|
|
1388
|
-
* @internal
|
|
1389
|
-
*/
|
|
1390
|
-
const CR = 13;
|
|
1391
|
-
/**
|
|
1392
|
-
* @internal
|
|
1393
|
-
*/
|
|
1394
|
-
const COLON = 58;
|
|
1395
|
-
/**
|
|
1396
|
-
* This is an evented, rec descent parser.
|
|
1397
|
-
* A stream of Octets can be passed and whenever it recognizes
|
|
1398
|
-
* a complete Frame or an incoming ping it will invoke the registered callbacks.
|
|
1399
|
-
*
|
|
1400
|
-
* All incoming Octets are fed into _onByte function.
|
|
1401
|
-
* Depending on current state the _onByte function keeps changing.
|
|
1402
|
-
* Depending on the state it keeps accumulating into _token and _results.
|
|
1403
|
-
* State is indicated by current value of _onByte, all states are named as _collect.
|
|
1404
|
-
*
|
|
1405
|
-
* STOMP standards https://stomp.github.io/stomp-specification-1.2.html
|
|
1406
|
-
* imply that all lengths are considered in bytes (instead of string lengths).
|
|
1407
|
-
* So, before actual parsing, if the incoming data is String it is converted to Octets.
|
|
1408
|
-
* This allows faithful implementation of the protocol and allows NULL Octets to be present in the body.
|
|
1409
|
-
*
|
|
1410
|
-
* There is no peek function on the incoming data.
|
|
1411
|
-
* When a state change occurs based on an Octet without consuming the Octet,
|
|
1412
|
-
* the Octet, after state change, is fed again (_reinjectByte).
|
|
1413
|
-
* This became possible as the state change can be determined by inspecting just one Octet.
|
|
1414
|
-
*
|
|
1415
|
-
* There are two modes to collect the body, if content-length header is there then it by counting Octets
|
|
1416
|
-
* otherwise it is determined by NULL terminator.
|
|
1417
|
-
*
|
|
1418
|
-
* Following the standards, the command and headers are converted to Strings
|
|
1419
|
-
* and the body is returned as Octets.
|
|
1420
|
-
* Headers are returned as an array and not as Hash - to allow multiple occurrence of an header.
|
|
1421
|
-
*
|
|
1422
|
-
* This parser does not use Regular Expressions as that can only operate on Strings.
|
|
1423
|
-
*
|
|
1424
|
-
* It handles if multiple STOMP frames are given as one chunk, a frame is split into multiple chunks, or
|
|
1425
|
-
* any combination there of. The parser remembers its state (any partial frame) and continues when a new chunk
|
|
1426
|
-
* is pushed.
|
|
1427
|
-
*
|
|
1428
|
-
* Typically the higher level function will convert headers to Hash, handle unescaping of header values
|
|
1429
|
-
* (which is protocol version specific), and convert body to text.
|
|
1430
|
-
*
|
|
1431
|
-
* Check the parser.spec.js to understand cases that this parser is supposed to handle.
|
|
1432
|
-
*
|
|
1433
|
-
* Part of `@stomp/stompjs`.
|
|
1434
|
-
*
|
|
1435
|
-
* @internal
|
|
1436
|
-
*/
|
|
1437
|
-
class Parser {
|
|
1438
|
-
constructor(onFrame, onIncomingPing) {
|
|
1439
|
-
this.onFrame = onFrame;
|
|
1440
|
-
this.onIncomingPing = onIncomingPing;
|
|
1441
|
-
this._encoder = new TextEncoder();
|
|
1442
|
-
this._decoder = new TextDecoder();
|
|
1443
|
-
this._token = [];
|
|
1444
|
-
this._initState();
|
|
1445
|
-
}
|
|
1446
|
-
parseChunk(segment, appendMissingNULLonIncoming = false) {
|
|
1447
|
-
let chunk;
|
|
1448
|
-
if (segment instanceof ArrayBuffer) {
|
|
1449
|
-
chunk = new Uint8Array(segment);
|
|
1450
|
-
}
|
|
1451
|
-
else {
|
|
1452
|
-
chunk = this._encoder.encode(segment);
|
|
1453
|
-
}
|
|
1454
|
-
// See https://github.com/stomp-js/stompjs/issues/89
|
|
1455
|
-
// Remove when underlying issue is fixed.
|
|
1456
|
-
//
|
|
1457
|
-
// Send a NULL byte, if the last byte of a Text frame was not NULL.F
|
|
1458
|
-
if (appendMissingNULLonIncoming && chunk[chunk.length - 1] !== 0) {
|
|
1459
|
-
const chunkWithNull = new Uint8Array(chunk.length + 1);
|
|
1460
|
-
chunkWithNull.set(chunk, 0);
|
|
1461
|
-
chunkWithNull[chunk.length] = 0;
|
|
1462
|
-
chunk = chunkWithNull;
|
|
1463
|
-
}
|
|
1464
|
-
// tslint:disable-next-line:prefer-for-of
|
|
1465
|
-
for (let i = 0; i < chunk.length; i++) {
|
|
1466
|
-
const byte = chunk[i];
|
|
1467
|
-
this._onByte(byte);
|
|
1468
|
-
}
|
|
1469
|
-
}
|
|
1470
|
-
// The following implements a simple Rec Descent Parser.
|
|
1471
|
-
// The grammar is simple and just one byte tells what should be the next state
|
|
1472
|
-
_collectFrame(byte) {
|
|
1473
|
-
if (byte === NULL) {
|
|
1474
|
-
// Ignore
|
|
1475
|
-
return;
|
|
1476
|
-
}
|
|
1477
|
-
if (byte === CR) {
|
|
1478
|
-
// Ignore CR
|
|
1479
|
-
return;
|
|
1480
|
-
}
|
|
1481
|
-
if (byte === LF) {
|
|
1482
|
-
// Incoming Ping
|
|
1483
|
-
this.onIncomingPing();
|
|
1484
|
-
return;
|
|
1485
|
-
}
|
|
1486
|
-
this._onByte = this._collectCommand;
|
|
1487
|
-
this._reinjectByte(byte);
|
|
1488
|
-
}
|
|
1489
|
-
_collectCommand(byte) {
|
|
1490
|
-
if (byte === CR) {
|
|
1491
|
-
// Ignore CR
|
|
1492
|
-
return;
|
|
1493
|
-
}
|
|
1494
|
-
if (byte === LF) {
|
|
1495
|
-
this._results.command = this._consumeTokenAsUTF8();
|
|
1496
|
-
this._onByte = this._collectHeaders;
|
|
1497
|
-
return;
|
|
1498
|
-
}
|
|
1499
|
-
this._consumeByte(byte);
|
|
1500
|
-
}
|
|
1501
|
-
_collectHeaders(byte) {
|
|
1502
|
-
if (byte === CR) {
|
|
1503
|
-
// Ignore CR
|
|
1504
|
-
return;
|
|
1505
|
-
}
|
|
1506
|
-
if (byte === LF) {
|
|
1507
|
-
this._setupCollectBody();
|
|
1508
|
-
return;
|
|
1509
|
-
}
|
|
1510
|
-
this._onByte = this._collectHeaderKey;
|
|
1511
|
-
this._reinjectByte(byte);
|
|
1512
|
-
}
|
|
1513
|
-
_reinjectByte(byte) {
|
|
1514
|
-
this._onByte(byte);
|
|
1515
|
-
}
|
|
1516
|
-
_collectHeaderKey(byte) {
|
|
1517
|
-
if (byte === COLON) {
|
|
1518
|
-
this._headerKey = this._consumeTokenAsUTF8();
|
|
1519
|
-
this._onByte = this._collectHeaderValue;
|
|
1520
|
-
return;
|
|
1521
|
-
}
|
|
1522
|
-
this._consumeByte(byte);
|
|
1523
|
-
}
|
|
1524
|
-
_collectHeaderValue(byte) {
|
|
1525
|
-
if (byte === CR) {
|
|
1526
|
-
// Ignore CR
|
|
1527
|
-
return;
|
|
1528
|
-
}
|
|
1529
|
-
if (byte === LF) {
|
|
1530
|
-
this._results.headers.push([this._headerKey, this._consumeTokenAsUTF8()]);
|
|
1531
|
-
this._headerKey = undefined;
|
|
1532
|
-
this._onByte = this._collectHeaders;
|
|
1533
|
-
return;
|
|
1504
|
+
class HeartbeatInfo {
|
|
1505
|
+
constructor(client) {
|
|
1506
|
+
this.client = client;
|
|
1534
1507
|
}
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
_setupCollectBody() {
|
|
1538
|
-
const contentLengthHeader = this._results.headers.filter((header) => {
|
|
1539
|
-
return header[0] === 'content-length';
|
|
1540
|
-
})[0];
|
|
1541
|
-
if (contentLengthHeader) {
|
|
1542
|
-
this._bodyBytesRemaining = parseInt(contentLengthHeader[1], 10);
|
|
1543
|
-
this._onByte = this._collectBodyFixedSize;
|
|
1508
|
+
get outgoing() {
|
|
1509
|
+
return this.client.heartbeatOutgoing;
|
|
1544
1510
|
}
|
|
1545
|
-
|
|
1546
|
-
this.
|
|
1511
|
+
set outgoing(value) {
|
|
1512
|
+
this.client.heartbeatOutgoing = value;
|
|
1547
1513
|
}
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
if (byte === NULL) {
|
|
1551
|
-
this._retrievedBody();
|
|
1552
|
-
return;
|
|
1514
|
+
get incoming() {
|
|
1515
|
+
return this.client.heartbeatIncoming;
|
|
1553
1516
|
}
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
_collectBodyFixedSize(byte) {
|
|
1557
|
-
// It is post decrement, so that we discard the trailing NULL octet
|
|
1558
|
-
if (this._bodyBytesRemaining-- === 0) {
|
|
1559
|
-
this._retrievedBody();
|
|
1560
|
-
return;
|
|
1517
|
+
set incoming(value) {
|
|
1518
|
+
this.client.heartbeatIncoming = value;
|
|
1561
1519
|
}
|
|
1562
|
-
this._consumeByte(byte);
|
|
1563
|
-
}
|
|
1564
|
-
_retrievedBody() {
|
|
1565
|
-
this._results.binaryBody = this._consumeTokenAsRaw();
|
|
1566
|
-
this.onFrame(this._results);
|
|
1567
|
-
this._initState();
|
|
1568
|
-
}
|
|
1569
|
-
// Rec Descent Parser helpers
|
|
1570
|
-
_consumeByte(byte) {
|
|
1571
|
-
this._token.push(byte);
|
|
1572
|
-
}
|
|
1573
|
-
_consumeTokenAsUTF8() {
|
|
1574
|
-
return this._decoder.decode(this._consumeTokenAsRaw());
|
|
1575
|
-
}
|
|
1576
|
-
_consumeTokenAsRaw() {
|
|
1577
|
-
const rawResult = new Uint8Array(this._token);
|
|
1578
|
-
this._token = [];
|
|
1579
|
-
return rawResult;
|
|
1580
1520
|
}
|
|
1581
|
-
_initState() {
|
|
1582
|
-
this._results = {
|
|
1583
|
-
command: undefined,
|
|
1584
|
-
headers: [],
|
|
1585
|
-
binaryBody: undefined,
|
|
1586
|
-
};
|
|
1587
|
-
this._token = [];
|
|
1588
|
-
this._headerKey = undefined;
|
|
1589
|
-
this._onByte = this._collectFrame;
|
|
1590
|
-
}
|
|
1591
|
-
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
/***/ }),
|
|
1595
|
-
|
|
1596
|
-
/***/ "./src/stomp-config.ts":
|
|
1597
|
-
/*!*****************************!*\
|
|
1598
|
-
!*** ./src/stomp-config.ts ***!
|
|
1599
|
-
\*****************************/
|
|
1600
|
-
/*! exports provided: StompConfig */
|
|
1601
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1602
|
-
|
|
1603
|
-
"use strict";
|
|
1604
|
-
__webpack_require__.r(__webpack_exports__);
|
|
1605
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StompConfig", function() { return StompConfig; });
|
|
1606
|
-
/**
|
|
1607
|
-
* Configuration options for STOMP Client, each key corresponds to
|
|
1608
|
-
* field by the same name in {@link Client}. This can be passed to
|
|
1609
|
-
* the constructor of {@link Client} or to [Client#configure]{@link Client#configure}.
|
|
1610
|
-
*
|
|
1611
|
-
* There used to be a class with the same name in `@stomp/ng2-stompjs`, which has been replaced by
|
|
1612
|
-
* {@link RxStompConfig} and {@link InjectableRxStompConfig}.
|
|
1613
|
-
*
|
|
1614
|
-
* Part of `@stomp/stompjs`.
|
|
1615
|
-
*/
|
|
1616
|
-
class StompConfig {
|
|
1617
|
-
}
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
/***/ }),
|
|
1621
1521
|
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
// STOMP version 1.2 needs header values to be escaped
|
|
1662
|
-
if (this._connectedVersion === _versions__WEBPACK_IMPORTED_MODULE_4__["Versions"].V1_2) {
|
|
1663
|
-
this._escapeHeaderValues = true;
|
|
1664
|
-
}
|
|
1665
|
-
this._setupHeartbeat(frame.headers);
|
|
1666
|
-
this.onConnect(frame);
|
|
1667
|
-
},
|
|
1668
|
-
// [MESSAGE Frame](http://stomp.github.com/stomp-specification-1.2.html#MESSAGE)
|
|
1669
|
-
MESSAGE: frame => {
|
|
1670
|
-
// the callback is registered when the client calls
|
|
1671
|
-
// `subscribe()`.
|
|
1672
|
-
// If there is no registered subscription for the received message,
|
|
1673
|
-
// the default `onUnhandledMessage` callback is used that the client can set.
|
|
1674
|
-
// This is useful for subscriptions that are automatically created
|
|
1675
|
-
// on the browser side (e.g. [RabbitMQ's temporary
|
|
1676
|
-
// queues](http://www.rabbitmq.com/stomp.html)).
|
|
1677
|
-
const subscription = frame.headers.subscription;
|
|
1678
|
-
const onReceive = this._subscriptions[subscription] || this.onUnhandledMessage;
|
|
1679
|
-
// bless the frame to be a Message
|
|
1680
|
-
const message = frame;
|
|
1681
|
-
const client = this;
|
|
1682
|
-
const messageId = this._connectedVersion === _versions__WEBPACK_IMPORTED_MODULE_4__["Versions"].V1_2
|
|
1683
|
-
? message.headers.ack
|
|
1684
|
-
: message.headers['message-id'];
|
|
1685
|
-
// add `ack()` and `nack()` methods directly to the returned frame
|
|
1686
|
-
// so that a simple call to `message.ack()` can acknowledge the message.
|
|
1687
|
-
message.ack = (headers = {}) => {
|
|
1688
|
-
return client.ack(messageId, subscription, headers);
|
|
1689
|
-
};
|
|
1690
|
-
message.nack = (headers = {}) => {
|
|
1691
|
-
return client.nack(messageId, subscription, headers);
|
|
1692
|
-
};
|
|
1693
|
-
onReceive(message);
|
|
1694
|
-
},
|
|
1695
|
-
// [RECEIPT Frame](http://stomp.github.com/stomp-specification-1.2.html#RECEIPT)
|
|
1696
|
-
RECEIPT: frame => {
|
|
1697
|
-
const callback = this._receiptWatchers[frame.headers['receipt-id']];
|
|
1698
|
-
if (callback) {
|
|
1699
|
-
callback(frame);
|
|
1700
|
-
// Server will acknowledge only once, remove the callback
|
|
1701
|
-
delete this._receiptWatchers[frame.headers['receipt-id']];
|
|
1702
|
-
}
|
|
1703
|
-
else {
|
|
1704
|
-
this.onUnhandledReceipt(frame);
|
|
1705
|
-
}
|
|
1706
|
-
},
|
|
1707
|
-
// [ERROR Frame](http://stomp.github.com/stomp-specification-1.2.html#ERROR)
|
|
1708
|
-
ERROR: frame => {
|
|
1709
|
-
this.onStompError(frame);
|
|
1710
|
-
},
|
|
1711
|
-
};
|
|
1712
|
-
// used to index subscribers
|
|
1713
|
-
this._counter = 0;
|
|
1714
|
-
// subscription callbacks indexed by subscriber's ID
|
|
1715
|
-
this._subscriptions = {};
|
|
1716
|
-
// receipt-watchers indexed by receipts-ids
|
|
1717
|
-
this._receiptWatchers = {};
|
|
1718
|
-
this._partialData = '';
|
|
1719
|
-
this._escapeHeaderValues = false;
|
|
1720
|
-
this._lastServerActivityTS = Date.now();
|
|
1721
|
-
this.configure(config);
|
|
1722
|
-
}
|
|
1723
|
-
get connectedVersion() {
|
|
1724
|
-
return this._connectedVersion;
|
|
1725
|
-
}
|
|
1726
|
-
get connected() {
|
|
1727
|
-
return this._connected;
|
|
1728
|
-
}
|
|
1729
|
-
configure(conf) {
|
|
1730
|
-
// bulk assign all properties to this
|
|
1731
|
-
Object.assign(this, conf);
|
|
1732
|
-
}
|
|
1733
|
-
start() {
|
|
1734
|
-
const parser = new _parser__WEBPACK_IMPORTED_MODULE_2__["Parser"](
|
|
1735
|
-
// On Frame
|
|
1736
|
-
rawFrame => {
|
|
1737
|
-
const frame = _frame_impl__WEBPACK_IMPORTED_MODULE_1__["FrameImpl"].fromRawFrame(rawFrame, this._escapeHeaderValues);
|
|
1738
|
-
// if this.logRawCommunication is set, the rawChunk is logged at this._webSocket.onmessage
|
|
1739
|
-
if (!this.logRawCommunication) {
|
|
1740
|
-
this.debug(`<<< ${frame}`);
|
|
1741
|
-
}
|
|
1742
|
-
const serverFrameHandler = this._serverFrameHandlers[frame.command] || this.onUnhandledFrame;
|
|
1743
|
-
serverFrameHandler(frame);
|
|
1744
|
-
},
|
|
1745
|
-
// On Incoming Ping
|
|
1746
|
-
() => {
|
|
1747
|
-
this.debug('<<< PONG');
|
|
1748
|
-
});
|
|
1749
|
-
this._webSocket.onmessage = (evt) => {
|
|
1750
|
-
this.debug('Received data');
|
|
1751
|
-
this._lastServerActivityTS = Date.now();
|
|
1752
|
-
if (this.logRawCommunication) {
|
|
1753
|
-
const rawChunkAsString = evt.data instanceof ArrayBuffer
|
|
1754
|
-
? new TextDecoder().decode(evt.data)
|
|
1755
|
-
: evt.data;
|
|
1756
|
-
this.debug(`<<< ${rawChunkAsString}`);
|
|
1522
|
+
/**
|
|
1523
|
+
* Available for backward compatibility, please shift to using {@link Client}.
|
|
1524
|
+
*
|
|
1525
|
+
* **Deprecated**
|
|
1526
|
+
*
|
|
1527
|
+
* Part of `@stomp/stompjs`.
|
|
1528
|
+
*
|
|
1529
|
+
* To upgrade, please follow the [Upgrade Guide](../additional-documentation/upgrading.html)
|
|
1530
|
+
*/
|
|
1531
|
+
class CompatClient extends Client {
|
|
1532
|
+
/**
|
|
1533
|
+
* Available for backward compatibility, please shift to using {@link Client}
|
|
1534
|
+
* and [Client#webSocketFactory]{@link Client#webSocketFactory}.
|
|
1535
|
+
*
|
|
1536
|
+
* **Deprecated**
|
|
1537
|
+
*
|
|
1538
|
+
* @internal
|
|
1539
|
+
*/
|
|
1540
|
+
constructor(webSocketFactory) {
|
|
1541
|
+
super();
|
|
1542
|
+
/**
|
|
1543
|
+
* It is no op now. No longer needed. Large packets work out of the box.
|
|
1544
|
+
*/
|
|
1545
|
+
this.maxWebSocketFrameSize = 16 * 1024;
|
|
1546
|
+
this._heartbeatInfo = new HeartbeatInfo(this);
|
|
1547
|
+
this.reconnect_delay = 0;
|
|
1548
|
+
this.webSocketFactory = webSocketFactory;
|
|
1549
|
+
// Default from previous version
|
|
1550
|
+
this.debug = (...message) => {
|
|
1551
|
+
console.log(...message);
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
_parseConnect(...args) {
|
|
1555
|
+
let closeEventCallback;
|
|
1556
|
+
let connectCallback;
|
|
1557
|
+
let errorCallback;
|
|
1558
|
+
let headers = {};
|
|
1559
|
+
if (args.length < 2) {
|
|
1560
|
+
throw new Error('Connect requires at least 2 arguments');
|
|
1757
1561
|
}
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
_setupHeartbeat(headers) {
|
|
1782
|
-
if (headers.version !== _versions__WEBPACK_IMPORTED_MODULE_4__["Versions"].V1_1 &&
|
|
1783
|
-
headers.version !== _versions__WEBPACK_IMPORTED_MODULE_4__["Versions"].V1_2) {
|
|
1784
|
-
return;
|
|
1785
|
-
}
|
|
1786
|
-
// It is valid for the server to not send this header
|
|
1787
|
-
// https://stomp.github.io/stomp-specification-1.2.html#Heart-beating
|
|
1788
|
-
if (!headers['heart-beat']) {
|
|
1789
|
-
return;
|
|
1790
|
-
}
|
|
1791
|
-
// heart-beat header received from the server looks like:
|
|
1792
|
-
//
|
|
1793
|
-
// heart-beat: sx, sy
|
|
1794
|
-
const [serverOutgoing, serverIncoming] = headers['heart-beat']
|
|
1795
|
-
.split(',')
|
|
1796
|
-
.map((v) => parseInt(v, 10));
|
|
1797
|
-
if (this.heartbeatOutgoing !== 0 && serverIncoming !== 0) {
|
|
1798
|
-
const ttl = Math.max(this.heartbeatOutgoing, serverIncoming);
|
|
1799
|
-
this.debug(`send PING every ${ttl}ms`);
|
|
1800
|
-
this._pinger = setInterval(() => {
|
|
1801
|
-
if (this._webSocket.readyState === _types__WEBPACK_IMPORTED_MODULE_3__["StompSocketState"].OPEN) {
|
|
1802
|
-
this._webSocket.send(_byte__WEBPACK_IMPORTED_MODULE_0__["BYTE"].LF);
|
|
1803
|
-
this.debug('>>> PING');
|
|
1804
|
-
}
|
|
1805
|
-
}, ttl);
|
|
1806
|
-
}
|
|
1807
|
-
if (this.heartbeatIncoming !== 0 && serverOutgoing !== 0) {
|
|
1808
|
-
const ttl = Math.max(this.heartbeatIncoming, serverOutgoing);
|
|
1809
|
-
this.debug(`check PONG every ${ttl}ms`);
|
|
1810
|
-
this._ponger = setInterval(() => {
|
|
1811
|
-
const delta = Date.now() - this._lastServerActivityTS;
|
|
1812
|
-
// We wait twice the TTL to be flexible on window's setInterval calls
|
|
1813
|
-
if (delta > ttl * 2) {
|
|
1814
|
-
this.debug(`did not receive server activity for the last ${delta}ms`);
|
|
1815
|
-
this._closeOrDiscardWebsocket();
|
|
1562
|
+
if (typeof args[1] === 'function') {
|
|
1563
|
+
[headers, connectCallback, errorCallback, closeEventCallback] = args;
|
|
1564
|
+
}
|
|
1565
|
+
else {
|
|
1566
|
+
switch (args.length) {
|
|
1567
|
+
case 6:
|
|
1568
|
+
[
|
|
1569
|
+
headers.login,
|
|
1570
|
+
headers.passcode,
|
|
1571
|
+
connectCallback,
|
|
1572
|
+
errorCallback,
|
|
1573
|
+
closeEventCallback,
|
|
1574
|
+
headers.host,
|
|
1575
|
+
] = args;
|
|
1576
|
+
break;
|
|
1577
|
+
default:
|
|
1578
|
+
[
|
|
1579
|
+
headers.login,
|
|
1580
|
+
headers.passcode,
|
|
1581
|
+
connectCallback,
|
|
1582
|
+
errorCallback,
|
|
1583
|
+
closeEventCallback,
|
|
1584
|
+
] = args;
|
|
1816
1585
|
}
|
|
1817
|
-
}, ttl);
|
|
1818
|
-
}
|
|
1819
|
-
}
|
|
1820
|
-
_closeOrDiscardWebsocket() {
|
|
1821
|
-
if (this.discardWebsocketOnCommFailure) {
|
|
1822
|
-
this.debug('Discarding websocket, the underlying socket may linger for a while');
|
|
1823
|
-
this._discardWebsocket();
|
|
1824
|
-
}
|
|
1825
|
-
else {
|
|
1826
|
-
this.debug('Issuing close on the websocket');
|
|
1827
|
-
this._closeWebsocket();
|
|
1828
|
-
}
|
|
1829
|
-
}
|
|
1830
|
-
forceDisconnect() {
|
|
1831
|
-
if (this._webSocket) {
|
|
1832
|
-
if (this._webSocket.readyState === _types__WEBPACK_IMPORTED_MODULE_3__["StompSocketState"].CONNECTING ||
|
|
1833
|
-
this._webSocket.readyState === _types__WEBPACK_IMPORTED_MODULE_3__["StompSocketState"].OPEN) {
|
|
1834
|
-
this._closeOrDiscardWebsocket();
|
|
1835
1586
|
}
|
|
1587
|
+
return [headers, connectCallback, errorCallback, closeEventCallback];
|
|
1836
1588
|
}
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
if (typeof rawChunk !== 'string' || !this.splitLargeFrames) {
|
|
1869
|
-
this._webSocket.send(rawChunk);
|
|
1870
|
-
}
|
|
1871
|
-
else {
|
|
1872
|
-
let out = rawChunk;
|
|
1873
|
-
while (out.length > 0) {
|
|
1874
|
-
const chunk = out.substring(0, this.maxWebSocketChunkSize);
|
|
1875
|
-
out = out.substring(this.maxWebSocketChunkSize);
|
|
1876
|
-
this._webSocket.send(chunk);
|
|
1877
|
-
this.debug(`chunk sent = ${chunk.length}, remaining = ${out.length}`);
|
|
1589
|
+
/**
|
|
1590
|
+
* Available for backward compatibility, please shift to using [Client#activate]{@link Client#activate}.
|
|
1591
|
+
*
|
|
1592
|
+
* **Deprecated**
|
|
1593
|
+
*
|
|
1594
|
+
* The `connect` method accepts different number of arguments and types. See the Overloads list. Use the
|
|
1595
|
+
* version with headers to pass your broker specific options.
|
|
1596
|
+
*
|
|
1597
|
+
* overloads:
|
|
1598
|
+
* - connect(headers, connectCallback)
|
|
1599
|
+
* - connect(headers, connectCallback, errorCallback)
|
|
1600
|
+
* - connect(login, passcode, connectCallback)
|
|
1601
|
+
* - connect(login, passcode, connectCallback, errorCallback)
|
|
1602
|
+
* - connect(login, passcode, connectCallback, errorCallback, closeEventCallback)
|
|
1603
|
+
* - connect(login, passcode, connectCallback, errorCallback, closeEventCallback, host)
|
|
1604
|
+
*
|
|
1605
|
+
* params:
|
|
1606
|
+
* - headers, see [Client#connectHeaders]{@link Client#connectHeaders}
|
|
1607
|
+
* - connectCallback, see [Client#onConnect]{@link Client#onConnect}
|
|
1608
|
+
* - errorCallback, see [Client#onStompError]{@link Client#onStompError}
|
|
1609
|
+
* - closeEventCallback, see [Client#onWebSocketClose]{@link Client#onWebSocketClose}
|
|
1610
|
+
* - login [String], see [Client#connectHeaders](../classes/Client.html#connectHeaders)
|
|
1611
|
+
* - passcode [String], [Client#connectHeaders](../classes/Client.html#connectHeaders)
|
|
1612
|
+
* - host [String], see [Client#connectHeaders](../classes/Client.html#connectHeaders)
|
|
1613
|
+
*
|
|
1614
|
+
* To upgrade, please follow the [Upgrade Guide](../additional-documentation/upgrading.html)
|
|
1615
|
+
*/
|
|
1616
|
+
connect(...args) {
|
|
1617
|
+
const out = this._parseConnect(...args);
|
|
1618
|
+
if (out[0]) {
|
|
1619
|
+
this.connectHeaders = out[0];
|
|
1878
1620
|
}
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
dispose() {
|
|
1882
|
-
if (this.connected) {
|
|
1883
|
-
try {
|
|
1884
|
-
// clone before updating
|
|
1885
|
-
const disconnectHeaders = Object.assign({}, this.disconnectHeaders);
|
|
1886
|
-
if (!disconnectHeaders.receipt) {
|
|
1887
|
-
disconnectHeaders.receipt = `close-${this._counter++}`;
|
|
1888
|
-
}
|
|
1889
|
-
this.watchForReceipt(disconnectHeaders.receipt, frame => {
|
|
1890
|
-
this._closeWebsocket();
|
|
1891
|
-
this._cleanUp();
|
|
1892
|
-
this.onDisconnect(frame);
|
|
1893
|
-
});
|
|
1894
|
-
this._transmit({ command: 'DISCONNECT', headers: disconnectHeaders });
|
|
1621
|
+
if (out[1]) {
|
|
1622
|
+
this.onConnect = out[1];
|
|
1895
1623
|
}
|
|
1896
|
-
|
|
1897
|
-
this.
|
|
1624
|
+
if (out[2]) {
|
|
1625
|
+
this.onStompError = out[2];
|
|
1898
1626
|
}
|
|
1627
|
+
if (out[3]) {
|
|
1628
|
+
this.onWebSocketClose = out[3];
|
|
1629
|
+
}
|
|
1630
|
+
super.activate();
|
|
1899
1631
|
}
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1632
|
+
/**
|
|
1633
|
+
* Available for backward compatibility, please shift to using [Client#deactivate]{@link Client#deactivate}.
|
|
1634
|
+
*
|
|
1635
|
+
* **Deprecated**
|
|
1636
|
+
*
|
|
1637
|
+
* See:
|
|
1638
|
+
* [Client#onDisconnect]{@link Client#onDisconnect}, and
|
|
1639
|
+
* [Client#disconnectHeaders]{@link Client#disconnectHeaders}
|
|
1640
|
+
*
|
|
1641
|
+
* To upgrade, please follow the [Upgrade Guide](../additional-documentation/upgrading.html)
|
|
1642
|
+
*/
|
|
1643
|
+
disconnect(disconnectCallback, headers = {}) {
|
|
1644
|
+
if (disconnectCallback) {
|
|
1645
|
+
this.onDisconnect = disconnectCallback;
|
|
1904
1646
|
}
|
|
1647
|
+
this.disconnectHeaders = headers;
|
|
1648
|
+
super.deactivate();
|
|
1905
1649
|
}
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1650
|
+
/**
|
|
1651
|
+
* Available for backward compatibility, use [Client#publish]{@link Client#publish}.
|
|
1652
|
+
*
|
|
1653
|
+
* Send a message to a named destination. Refer to your STOMP broker documentation for types
|
|
1654
|
+
* and naming of destinations. The headers will, typically, be available to the subscriber.
|
|
1655
|
+
* However, there may be special purpose headers corresponding to your STOMP broker.
|
|
1656
|
+
*
|
|
1657
|
+
* **Deprecated**, use [Client#publish]{@link Client#publish}
|
|
1658
|
+
*
|
|
1659
|
+
* Note: Body must be String. You will need to covert the payload to string in case it is not string (e.g. JSON)
|
|
1660
|
+
*
|
|
1661
|
+
* ```javascript
|
|
1662
|
+
* client.send("/queue/test", {priority: 9}, "Hello, STOMP");
|
|
1663
|
+
*
|
|
1664
|
+
* // If you want to send a message with a body, you must also pass the headers argument.
|
|
1665
|
+
* client.send("/queue/test", {}, "Hello, STOMP");
|
|
1666
|
+
* ```
|
|
1667
|
+
*
|
|
1668
|
+
* To upgrade, please follow the [Upgrade Guide](../additional-documentation/upgrading.html)
|
|
1669
|
+
*/
|
|
1670
|
+
send(destination, headers = {}, body = '') {
|
|
1671
|
+
headers = Object.assign({}, headers);
|
|
1672
|
+
const skipContentLengthHeader = headers['content-length'] === false;
|
|
1673
|
+
if (skipContentLengthHeader) {
|
|
1674
|
+
delete headers['content-length'];
|
|
1675
|
+
}
|
|
1676
|
+
this.publish({
|
|
1677
|
+
destination,
|
|
1678
|
+
headers: headers,
|
|
1679
|
+
body,
|
|
1680
|
+
skipContentLengthHeader,
|
|
1681
|
+
});
|
|
1911
1682
|
}
|
|
1912
|
-
|
|
1913
|
-
|
|
1683
|
+
/**
|
|
1684
|
+
* Available for backward compatibility, renamed to [Client#reconnectDelay]{@link Client#reconnectDelay}.
|
|
1685
|
+
*
|
|
1686
|
+
* **Deprecated**
|
|
1687
|
+
*/
|
|
1688
|
+
set reconnect_delay(value) {
|
|
1689
|
+
this.reconnectDelay = value;
|
|
1914
1690
|
}
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
body,
|
|
1923
|
-
binaryBody,
|
|
1924
|
-
skipContentLengthHeader,
|
|
1925
|
-
});
|
|
1926
|
-
}
|
|
1927
|
-
watchForReceipt(receiptId, callback) {
|
|
1928
|
-
this._receiptWatchers[receiptId] = callback;
|
|
1929
|
-
}
|
|
1930
|
-
subscribe(destination, callback, headers = {}) {
|
|
1931
|
-
headers = Object.assign({}, headers);
|
|
1932
|
-
if (!headers.id) {
|
|
1933
|
-
headers.id = `sub-${this._counter++}`;
|
|
1934
|
-
}
|
|
1935
|
-
headers.destination = destination;
|
|
1936
|
-
this._subscriptions[headers.id] = callback;
|
|
1937
|
-
this._transmit({ command: 'SUBSCRIBE', headers });
|
|
1938
|
-
const client = this;
|
|
1939
|
-
return {
|
|
1940
|
-
id: headers.id,
|
|
1941
|
-
unsubscribe(hdrs) {
|
|
1942
|
-
return client.unsubscribe(headers.id, hdrs);
|
|
1943
|
-
},
|
|
1944
|
-
};
|
|
1945
|
-
}
|
|
1946
|
-
unsubscribe(id, headers = {}) {
|
|
1947
|
-
headers = Object.assign({}, headers);
|
|
1948
|
-
delete this._subscriptions[id];
|
|
1949
|
-
headers.id = id;
|
|
1950
|
-
this._transmit({ command: 'UNSUBSCRIBE', headers });
|
|
1951
|
-
}
|
|
1952
|
-
begin(transactionId) {
|
|
1953
|
-
const txId = transactionId || `tx-${this._counter++}`;
|
|
1954
|
-
this._transmit({
|
|
1955
|
-
command: 'BEGIN',
|
|
1956
|
-
headers: {
|
|
1957
|
-
transaction: txId,
|
|
1958
|
-
},
|
|
1959
|
-
});
|
|
1960
|
-
const client = this;
|
|
1961
|
-
return {
|
|
1962
|
-
id: txId,
|
|
1963
|
-
commit() {
|
|
1964
|
-
client.commit(txId);
|
|
1965
|
-
},
|
|
1966
|
-
abort() {
|
|
1967
|
-
client.abort(txId);
|
|
1968
|
-
},
|
|
1969
|
-
};
|
|
1970
|
-
}
|
|
1971
|
-
commit(transactionId) {
|
|
1972
|
-
this._transmit({
|
|
1973
|
-
command: 'COMMIT',
|
|
1974
|
-
headers: {
|
|
1975
|
-
transaction: transactionId,
|
|
1976
|
-
},
|
|
1977
|
-
});
|
|
1978
|
-
}
|
|
1979
|
-
abort(transactionId) {
|
|
1980
|
-
this._transmit({
|
|
1981
|
-
command: 'ABORT',
|
|
1982
|
-
headers: {
|
|
1983
|
-
transaction: transactionId,
|
|
1984
|
-
},
|
|
1985
|
-
});
|
|
1986
|
-
}
|
|
1987
|
-
ack(messageId, subscriptionId, headers = {}) {
|
|
1988
|
-
headers = Object.assign({}, headers);
|
|
1989
|
-
if (this._connectedVersion === _versions__WEBPACK_IMPORTED_MODULE_4__["Versions"].V1_2) {
|
|
1990
|
-
headers.id = messageId;
|
|
1691
|
+
/**
|
|
1692
|
+
* Available for backward compatibility, renamed to [Client#webSocket]{@link Client#webSocket}.
|
|
1693
|
+
*
|
|
1694
|
+
* **Deprecated**
|
|
1695
|
+
*/
|
|
1696
|
+
get ws() {
|
|
1697
|
+
return this.webSocket;
|
|
1991
1698
|
}
|
|
1992
|
-
|
|
1993
|
-
|
|
1699
|
+
/**
|
|
1700
|
+
* Available for backward compatibility, renamed to [Client#connectedVersion]{@link Client#connectedVersion}.
|
|
1701
|
+
*
|
|
1702
|
+
* **Deprecated**
|
|
1703
|
+
*/
|
|
1704
|
+
get version() {
|
|
1705
|
+
return this.connectedVersion;
|
|
1994
1706
|
}
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
1707
|
+
/**
|
|
1708
|
+
* Available for backward compatibility, renamed to [Client#onUnhandledMessage]{@link Client#onUnhandledMessage}.
|
|
1709
|
+
*
|
|
1710
|
+
* **Deprecated**
|
|
1711
|
+
*/
|
|
1712
|
+
get onreceive() {
|
|
1713
|
+
return this.onUnhandledMessage;
|
|
1714
|
+
}
|
|
1715
|
+
/**
|
|
1716
|
+
* Available for backward compatibility, renamed to [Client#onUnhandledMessage]{@link Client#onUnhandledMessage}.
|
|
1717
|
+
*
|
|
1718
|
+
* **Deprecated**
|
|
1719
|
+
*/
|
|
1720
|
+
set onreceive(value) {
|
|
1721
|
+
this.onUnhandledMessage = value;
|
|
1722
|
+
}
|
|
1723
|
+
/**
|
|
1724
|
+
* Available for backward compatibility, renamed to [Client#onUnhandledReceipt]{@link Client#onUnhandledReceipt}.
|
|
1725
|
+
* Prefer using [Client#watchForReceipt]{@link Client#watchForReceipt}.
|
|
1726
|
+
*
|
|
1727
|
+
* **Deprecated**
|
|
1728
|
+
*/
|
|
1729
|
+
get onreceipt() {
|
|
1730
|
+
return this.onUnhandledReceipt;
|
|
1731
|
+
}
|
|
1732
|
+
/**
|
|
1733
|
+
* Available for backward compatibility, renamed to [Client#onUnhandledReceipt]{@link Client#onUnhandledReceipt}.
|
|
1734
|
+
*
|
|
1735
|
+
* **Deprecated**
|
|
1736
|
+
*/
|
|
1737
|
+
set onreceipt(value) {
|
|
1738
|
+
this.onUnhandledReceipt = value;
|
|
1739
|
+
}
|
|
1740
|
+
/**
|
|
1741
|
+
* Available for backward compatibility, renamed to [Client#heartbeatIncoming]{@link Client#heartbeatIncoming}
|
|
1742
|
+
* [Client#heartbeatOutgoing]{@link Client#heartbeatOutgoing}.
|
|
1743
|
+
*
|
|
1744
|
+
* **Deprecated**
|
|
1745
|
+
*/
|
|
1746
|
+
get heartbeat() {
|
|
1747
|
+
return this._heartbeatInfo;
|
|
2002
1748
|
}
|
|
2003
|
-
|
|
2004
|
-
|
|
1749
|
+
/**
|
|
1750
|
+
* Available for backward compatibility, renamed to [Client#heartbeatIncoming]{@link Client#heartbeatIncoming}
|
|
1751
|
+
* [Client#heartbeatOutgoing]{@link Client#heartbeatOutgoing}.
|
|
1752
|
+
*
|
|
1753
|
+
* **Deprecated**
|
|
1754
|
+
*/
|
|
1755
|
+
set heartbeat(value) {
|
|
1756
|
+
this.heartbeatIncoming = value.incoming;
|
|
1757
|
+
this.heartbeatOutgoing = value.outgoing;
|
|
2005
1758
|
}
|
|
2006
|
-
headers.subscription = subscriptionId;
|
|
2007
|
-
return this._transmit({ command: 'NACK', headers });
|
|
2008
1759
|
}
|
|
2009
|
-
}
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
/***/ }),
|
|
2013
|
-
|
|
2014
|
-
/***/ "./src/stomp-headers.ts":
|
|
2015
|
-
/*!******************************!*\
|
|
2016
|
-
!*** ./src/stomp-headers.ts ***!
|
|
2017
|
-
\******************************/
|
|
2018
|
-
/*! exports provided: StompHeaders */
|
|
2019
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
2020
|
-
|
|
2021
|
-
"use strict";
|
|
2022
|
-
__webpack_require__.r(__webpack_exports__);
|
|
2023
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StompHeaders", function() { return StompHeaders; });
|
|
2024
|
-
/**
|
|
2025
|
-
* STOMP headers. Many functions calls will accept headers as parameters.
|
|
2026
|
-
* The headers sent by Broker will be available as [IFrame#headers]{@link IFrame#headers}.
|
|
2027
|
-
*
|
|
2028
|
-
* `key` and `value` must be valid strings.
|
|
2029
|
-
* In addition, `key` must not contain `CR`, `LF`, or `:`.
|
|
2030
|
-
*
|
|
2031
|
-
* Part of `@stomp/stompjs`.
|
|
2032
|
-
*/
|
|
2033
|
-
class StompHeaders {
|
|
2034
|
-
}
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
/***/ }),
|
|
2038
|
-
|
|
2039
|
-
/***/ "./src/stomp-subscription.ts":
|
|
2040
|
-
/*!***********************************!*\
|
|
2041
|
-
!*** ./src/stomp-subscription.ts ***!
|
|
2042
|
-
\***********************************/
|
|
2043
|
-
/*! exports provided: StompSubscription */
|
|
2044
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
2045
|
-
|
|
2046
|
-
"use strict";
|
|
2047
|
-
__webpack_require__.r(__webpack_exports__);
|
|
2048
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StompSubscription", function() { return StompSubscription; });
|
|
2049
|
-
/**
|
|
2050
|
-
* Call [Client#subscribe]{@link Client#subscribe} to create a StompSubscription.
|
|
2051
|
-
*
|
|
2052
|
-
* Part of `@stomp/stompjs`.
|
|
2053
|
-
*/
|
|
2054
|
-
class StompSubscription {
|
|
2055
|
-
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
/***/ }),
|
|
2059
|
-
|
|
2060
|
-
/***/ "./src/types.ts":
|
|
2061
|
-
/*!**********************!*\
|
|
2062
|
-
!*** ./src/types.ts ***!
|
|
2063
|
-
\**********************/
|
|
2064
|
-
/*! exports provided: StompSocketState, ActivationState */
|
|
2065
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
2066
|
-
|
|
2067
|
-
"use strict";
|
|
2068
|
-
__webpack_require__.r(__webpack_exports__);
|
|
2069
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StompSocketState", function() { return StompSocketState; });
|
|
2070
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ActivationState", function() { return ActivationState; });
|
|
2071
|
-
/**
|
|
2072
|
-
* Possible states for the IStompSocket
|
|
2073
|
-
*/
|
|
2074
|
-
var StompSocketState;
|
|
2075
|
-
(function (StompSocketState) {
|
|
2076
|
-
StompSocketState[StompSocketState["CONNECTING"] = 0] = "CONNECTING";
|
|
2077
|
-
StompSocketState[StompSocketState["OPEN"] = 1] = "OPEN";
|
|
2078
|
-
StompSocketState[StompSocketState["CLOSING"] = 2] = "CLOSING";
|
|
2079
|
-
StompSocketState[StompSocketState["CLOSED"] = 3] = "CLOSED";
|
|
2080
|
-
})(StompSocketState || (StompSocketState = {}));
|
|
2081
|
-
/**
|
|
2082
|
-
* Possible activation state
|
|
2083
|
-
*/
|
|
2084
|
-
var ActivationState;
|
|
2085
|
-
(function (ActivationState) {
|
|
2086
|
-
ActivationState[ActivationState["ACTIVE"] = 0] = "ACTIVE";
|
|
2087
|
-
ActivationState[ActivationState["DEACTIVATING"] = 1] = "DEACTIVATING";
|
|
2088
|
-
ActivationState[ActivationState["INACTIVE"] = 2] = "INACTIVE";
|
|
2089
|
-
})(ActivationState || (ActivationState = {}));
|
|
2090
1760
|
|
|
2091
|
-
|
|
2092
|
-
/***/ }),
|
|
2093
|
-
|
|
2094
|
-
/***/ "./src/versions.ts":
|
|
2095
|
-
/*!*************************!*\
|
|
2096
|
-
!*** ./src/versions.ts ***!
|
|
2097
|
-
\*************************/
|
|
2098
|
-
/*! exports provided: Versions */
|
|
2099
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
2100
|
-
|
|
2101
|
-
"use strict";
|
|
2102
|
-
__webpack_require__.r(__webpack_exports__);
|
|
2103
|
-
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Versions", function() { return Versions; });
|
|
2104
|
-
/**
|
|
2105
|
-
* Supported STOMP versions
|
|
2106
|
-
*
|
|
2107
|
-
* Part of `@stomp/stompjs`.
|
|
2108
|
-
*/
|
|
2109
|
-
class Versions {
|
|
2110
1761
|
/**
|
|
2111
|
-
*
|
|
1762
|
+
* STOMP Class, acts like a factory to create {@link Client}.
|
|
2112
1763
|
*
|
|
2113
|
-
*
|
|
2114
|
-
*
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
}
|
|
2119
|
-
/**
|
|
2120
|
-
* Used as part of CONNECT STOMP Frame
|
|
1764
|
+
* Part of `@stomp/stompjs`.
|
|
1765
|
+
*
|
|
1766
|
+
* **Deprecated**
|
|
1767
|
+
*
|
|
1768
|
+
* It will be removed in next major version. Please switch to {@link Client}.
|
|
2121
1769
|
*/
|
|
2122
|
-
|
|
2123
|
-
|
|
1770
|
+
class Stomp {
|
|
1771
|
+
/**
|
|
1772
|
+
* This method creates a WebSocket client that is connected to
|
|
1773
|
+
* the STOMP server located at the url.
|
|
1774
|
+
*
|
|
1775
|
+
* ```javascript
|
|
1776
|
+
* var url = "ws://localhost:61614/stomp";
|
|
1777
|
+
* var client = Stomp.client(url);
|
|
1778
|
+
* ```
|
|
1779
|
+
*
|
|
1780
|
+
* **Deprecated**
|
|
1781
|
+
*
|
|
1782
|
+
* It will be removed in next major version. Please switch to {@link Client}
|
|
1783
|
+
* using [Client#brokerURL]{@link Client#brokerURL}.
|
|
1784
|
+
*/
|
|
1785
|
+
static client(url, protocols) {
|
|
1786
|
+
// This is a hack to allow another implementation than the standard
|
|
1787
|
+
// HTML5 WebSocket class.
|
|
1788
|
+
//
|
|
1789
|
+
// It is possible to use another class by calling
|
|
1790
|
+
//
|
|
1791
|
+
// Stomp.WebSocketClass = MozWebSocket
|
|
1792
|
+
//
|
|
1793
|
+
// *prior* to call `Stomp.client()`.
|
|
1794
|
+
//
|
|
1795
|
+
// This hack is deprecated and `Stomp.over()` method should be used
|
|
1796
|
+
// instead.
|
|
1797
|
+
// See remarks on the function Stomp.over
|
|
1798
|
+
if (protocols == null) {
|
|
1799
|
+
protocols = Versions.default.protocolVersions();
|
|
1800
|
+
}
|
|
1801
|
+
const wsFn = () => {
|
|
1802
|
+
const klass = Stomp.WebSocketClass || WebSocket;
|
|
1803
|
+
return new klass(url, protocols);
|
|
1804
|
+
};
|
|
1805
|
+
return new CompatClient(wsFn);
|
|
1806
|
+
}
|
|
1807
|
+
/**
|
|
1808
|
+
* This method is an alternative to [Stomp#client]{@link Stomp#client} to let the user
|
|
1809
|
+
* specify the WebSocket to use (either a standard HTML5 WebSocket or
|
|
1810
|
+
* a similar object).
|
|
1811
|
+
*
|
|
1812
|
+
* In order to support reconnection, the function Client._connect should be callable more than once.
|
|
1813
|
+
* While reconnecting
|
|
1814
|
+
* a new instance of underlying transport (TCP Socket, WebSocket or SockJS) will be needed. So, this function
|
|
1815
|
+
* alternatively allows passing a function that should return a new instance of the underlying socket.
|
|
1816
|
+
*
|
|
1817
|
+
* ```javascript
|
|
1818
|
+
* var client = Stomp.over(function(){
|
|
1819
|
+
* return new WebSocket('ws://localhost:15674/ws')
|
|
1820
|
+
* });
|
|
1821
|
+
* ```
|
|
1822
|
+
*
|
|
1823
|
+
* **Deprecated**
|
|
1824
|
+
*
|
|
1825
|
+
* It will be removed in next major version. Please switch to {@link Client}
|
|
1826
|
+
* using [Client#webSocketFactory]{@link Client#webSocketFactory}.
|
|
1827
|
+
*/
|
|
1828
|
+
static over(ws) {
|
|
1829
|
+
let wsFn;
|
|
1830
|
+
if (typeof ws === 'function') {
|
|
1831
|
+
wsFn = ws;
|
|
1832
|
+
}
|
|
1833
|
+
else {
|
|
1834
|
+
console.warn('Stomp.over did not receive a factory, auto reconnect will not work. ' +
|
|
1835
|
+
'Please see https://stomp-js.github.io/api-docs/latest/classes/Stomp.html#over');
|
|
1836
|
+
wsFn = () => ws;
|
|
1837
|
+
}
|
|
1838
|
+
return new CompatClient(wsFn);
|
|
1839
|
+
}
|
|
2124
1840
|
}
|
|
2125
1841
|
/**
|
|
2126
|
-
*
|
|
1842
|
+
* In case you need to use a non standard class for WebSocket.
|
|
1843
|
+
*
|
|
1844
|
+
* For example when using within NodeJS environment:
|
|
1845
|
+
*
|
|
1846
|
+
* ```javascript
|
|
1847
|
+
* StompJs = require('../../esm5/');
|
|
1848
|
+
* Stomp = StompJs.Stomp;
|
|
1849
|
+
* Stomp.WebSocketClass = require('websocket').w3cwebsocket;
|
|
1850
|
+
* ```
|
|
1851
|
+
*
|
|
1852
|
+
* **Deprecated**
|
|
1853
|
+
*
|
|
1854
|
+
*
|
|
1855
|
+
* It will be removed in next major version. Please switch to {@link Client}
|
|
1856
|
+
* using [Client#webSocketFactory]{@link Client#webSocketFactory}.
|
|
2127
1857
|
*/
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
*/
|
|
2143
|
-
Versions.V1_2 = '1.2';
|
|
2144
|
-
/**
|
|
2145
|
-
* @internal
|
|
2146
|
-
*/
|
|
2147
|
-
Versions.default = new Versions([
|
|
2148
|
-
Versions.V1_0,
|
|
2149
|
-
Versions.V1_1,
|
|
2150
|
-
Versions.V1_2,
|
|
2151
|
-
]);
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
/***/ }),
|
|
2155
|
-
|
|
2156
|
-
/***/ 0:
|
|
2157
|
-
/*!****************************!*\
|
|
2158
|
-
!*** multi ./src/index.ts ***!
|
|
2159
|
-
\****************************/
|
|
2160
|
-
/*! no static exports found */
|
|
2161
|
-
/***/ (function(module, exports, __webpack_require__) {
|
|
2162
|
-
|
|
2163
|
-
module.exports = __webpack_require__(/*! /home/kdeepak/MyWork/Tech/stomp/stompjs/src/index.ts */"./src/index.ts");
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
/***/ })
|
|
2167
|
-
|
|
2168
|
-
/******/ });
|
|
2169
|
-
});
|
|
2170
|
-
//# sourceMappingURL=stomp.umd.js.map
|
|
1858
|
+
// tslint:disable-next-line:variable-name
|
|
1859
|
+
Stomp.WebSocketClass = null;
|
|
1860
|
+
|
|
1861
|
+
exports.Client = Client;
|
|
1862
|
+
exports.CompatClient = CompatClient;
|
|
1863
|
+
exports.FrameImpl = FrameImpl;
|
|
1864
|
+
exports.Parser = Parser;
|
|
1865
|
+
exports.Stomp = Stomp;
|
|
1866
|
+
exports.StompConfig = StompConfig;
|
|
1867
|
+
exports.StompHeaders = StompHeaders;
|
|
1868
|
+
exports.Versions = Versions;
|
|
1869
|
+
|
|
1870
|
+
}));
|
|
1871
|
+
//# sourceMappingURL=stomp.umd.js.map
|