request-iframe 0.0.6 → 0.1.1
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/README.CN.md +220 -21
- package/README.md +221 -24
- package/esm/api/client.js +80 -0
- package/esm/api/server.js +61 -0
- package/esm/constants/index.js +289 -0
- package/esm/constants/messages.js +157 -0
- package/esm/core/client-server.js +294 -0
- package/esm/core/client.js +873 -0
- package/esm/core/request.js +27 -0
- package/esm/core/response.js +459 -0
- package/esm/core/server.js +776 -0
- package/esm/index.js +21 -0
- package/esm/interceptors/index.js +122 -0
- package/esm/message/channel.js +182 -0
- package/esm/message/dispatcher.js +418 -0
- package/esm/message/index.js +2 -0
- package/esm/stream/file-stream.js +289 -0
- package/esm/stream/index.js +44 -0
- package/esm/stream/readable-stream.js +539 -0
- package/esm/stream/stream-core.js +204 -0
- package/esm/stream/types.js +1 -0
- package/esm/stream/writable-stream.js +836 -0
- package/esm/types/index.js +1 -0
- package/esm/utils/ack.js +36 -0
- package/esm/utils/cache.js +147 -0
- package/esm/utils/cookie.js +352 -0
- package/esm/utils/debug.js +521 -0
- package/esm/utils/error.js +27 -0
- package/esm/utils/index.js +180 -0
- package/esm/utils/origin.js +30 -0
- package/esm/utils/path-match.js +148 -0
- package/esm/utils/protocol.js +157 -0
- package/library/api/client.d.ts.map +1 -1
- package/library/api/client.js +13 -5
- package/library/api/server.d.ts.map +1 -1
- package/library/api/server.js +6 -1
- package/library/constants/index.d.ts +59 -4
- package/library/constants/index.d.ts.map +1 -1
- package/library/constants/index.js +67 -9
- package/library/constants/messages.d.ts +8 -1
- package/library/constants/messages.d.ts.map +1 -1
- package/library/constants/messages.js +8 -1
- package/library/core/client-server.d.ts +7 -15
- package/library/core/client-server.d.ts.map +1 -1
- package/library/core/client-server.js +56 -44
- package/library/core/client.d.ts +4 -1
- package/library/core/client.d.ts.map +1 -1
- package/library/core/client.js +74 -31
- package/library/core/response.d.ts +21 -3
- package/library/core/response.d.ts.map +1 -1
- package/library/core/response.js +55 -7
- package/library/core/server.d.ts +34 -3
- package/library/core/server.d.ts.map +1 -1
- package/library/core/server.js +191 -21
- package/library/message/channel.d.ts +6 -0
- package/library/message/channel.d.ts.map +1 -1
- package/library/message/channel.js +2 -1
- package/library/message/dispatcher.d.ts +32 -0
- package/library/message/dispatcher.d.ts.map +1 -1
- package/library/message/dispatcher.js +131 -1
- package/library/stream/file-stream.d.ts +4 -0
- package/library/stream/file-stream.d.ts.map +1 -1
- package/library/stream/file-stream.js +61 -33
- package/library/stream/index.d.ts.map +1 -1
- package/library/stream/index.js +2 -0
- package/library/stream/readable-stream.d.ts +30 -11
- package/library/stream/readable-stream.d.ts.map +1 -1
- package/library/stream/readable-stream.js +368 -73
- package/library/stream/stream-core.d.ts +65 -0
- package/library/stream/stream-core.d.ts.map +1 -0
- package/library/stream/stream-core.js +211 -0
- package/library/stream/types.d.ts +203 -3
- package/library/stream/types.d.ts.map +1 -1
- package/library/stream/writable-stream.d.ts +59 -13
- package/library/stream/writable-stream.d.ts.map +1 -1
- package/library/stream/writable-stream.js +647 -197
- package/library/types/index.d.ts +70 -4
- package/library/types/index.d.ts.map +1 -1
- package/library/utils/ack.d.ts +2 -0
- package/library/utils/ack.d.ts.map +1 -0
- package/library/utils/ack.js +44 -0
- package/library/utils/debug.js +1 -1
- package/library/utils/index.d.ts +1 -0
- package/library/utils/index.d.ts.map +1 -1
- package/library/utils/index.js +19 -2
- package/library/utils/origin.d.ts +14 -0
- package/library/utils/origin.d.ts.map +1 -0
- package/library/utils/origin.js +35 -0
- package/package.json +30 -7
- package/react/README.md +16 -0
- package/react/esm/index.js +284 -0
- package/react/library/index.d.ts +1 -1
- package/react/library/index.d.ts.map +1 -1
- package/react/library/index.js +3 -3
- package/react/package.json +24 -2
|
@@ -0,0 +1,873 @@
|
|
|
1
|
+
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
|
|
2
|
+
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
3
|
+
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
4
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
5
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
6
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
7
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
8
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
9
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
10
|
+
import "core-js/modules/es.symbol.description.js";
|
|
11
|
+
import "core-js/modules/es.array.filter.js";
|
|
12
|
+
import "core-js/modules/es.array.from.js";
|
|
13
|
+
import "core-js/modules/es.array.iterator.js";
|
|
14
|
+
import "core-js/modules/es.array.slice.js";
|
|
15
|
+
import "core-js/modules/es.map.js";
|
|
16
|
+
import "core-js/modules/es.object.entries.js";
|
|
17
|
+
import "core-js/modules/es.promise.js";
|
|
18
|
+
import "core-js/modules/es.object.get-own-property-descriptors.js";
|
|
19
|
+
import "core-js/modules/es.regexp.exec.js";
|
|
20
|
+
import "core-js/modules/es.regexp.to-string.js";
|
|
21
|
+
import "core-js/modules/es.string.match.js";
|
|
22
|
+
import "core-js/modules/es.string.replace.js";
|
|
23
|
+
import "core-js/modules/es.string.starts-with.js";
|
|
24
|
+
import "core-js/modules/web.dom-collections.for-each.js";
|
|
25
|
+
import "core-js/modules/web.dom-collections.iterator.js";
|
|
26
|
+
import { RequestIframeError } from '../utils';
|
|
27
|
+
import { isAckMatch } from '../utils/ack';
|
|
28
|
+
import { detectContentType, blobToBase64, isWindowAvailable, matchOrigin } from '../utils';
|
|
29
|
+
import { generateRequestId, generateInstanceId, CookieStore } from '../utils';
|
|
30
|
+
import { RequestInterceptorManager, ResponseInterceptorManager, runRequestInterceptors, runResponseInterceptors } from '../interceptors';
|
|
31
|
+
import { DefaultTimeout, ErrorCode, MessageType, OriginConstant, HttpStatus, HttpStatusText, HttpHeader, Messages, formatMessage, StreamType as StreamTypeConstant } from '../constants';
|
|
32
|
+
import { IframeReadableStream, IframeFileReadableStream, isIframeWritableStream } from '../stream';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Client configuration options
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* RequestIframeClient implementation (only responsible for initiating requests, reuses server's listener)
|
|
40
|
+
*/
|
|
41
|
+
export class RequestIframeClientImpl {
|
|
42
|
+
/**
|
|
43
|
+
* Target server ID (remembered from responses)
|
|
44
|
+
* When a response is received, we remember the server's creatorId as the targetId for future requests
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
constructor(targetWindow, targetOrigin, server, options, instanceId) {
|
|
48
|
+
var _options$ackTimeout, _options$timeout, _options$asyncTimeout, _options$returnData;
|
|
49
|
+
/** Unique instance ID */
|
|
50
|
+
_defineProperty(this, "interceptors", {
|
|
51
|
+
request: new RequestInterceptorManager(),
|
|
52
|
+
response: new ResponseInterceptorManager()
|
|
53
|
+
});
|
|
54
|
+
/**
|
|
55
|
+
* Internal cookies storage
|
|
56
|
+
* - Automatically includes cookies matching the path when sending requests
|
|
57
|
+
* - Automatically parses Set-Cookie and saves when receiving response
|
|
58
|
+
*/
|
|
59
|
+
_defineProperty(this, "_cookieStore", new CookieStore());
|
|
60
|
+
/**
|
|
61
|
+
* Stream message handler map
|
|
62
|
+
* key: streamId
|
|
63
|
+
* value: stream message handler function
|
|
64
|
+
*/
|
|
65
|
+
_defineProperty(this, "streamHandlers", new Map());
|
|
66
|
+
this.id = instanceId || generateInstanceId();
|
|
67
|
+
this.targetWindow = targetWindow;
|
|
68
|
+
this.targetOrigin = targetOrigin;
|
|
69
|
+
this.server = server;
|
|
70
|
+
this.secretKey = options === null || options === void 0 ? void 0 : options.secretKey;
|
|
71
|
+
|
|
72
|
+
// Provide fallback target for auto-ack (useful when MessageEvent.source is missing in tests)
|
|
73
|
+
this.server.messageDispatcher.setFallbackTarget(this.targetWindow, this.targetOrigin);
|
|
74
|
+
|
|
75
|
+
// Build origin validator (incoming messages)
|
|
76
|
+
if (options !== null && options !== void 0 && options.validateOrigin) {
|
|
77
|
+
this.originValidator = (origin, data, context) => options.validateOrigin(origin, data, context);
|
|
78
|
+
} else if (options !== null && options !== void 0 && options.allowedOrigins) {
|
|
79
|
+
var matcher = options.allowedOrigins;
|
|
80
|
+
this.originValidator = origin => matchOrigin(origin, matcher);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Set default timeout configuration
|
|
84
|
+
this.defaultAckTimeout = (_options$ackTimeout = options === null || options === void 0 ? void 0 : options.ackTimeout) !== null && _options$ackTimeout !== void 0 ? _options$ackTimeout : DefaultTimeout.ACK;
|
|
85
|
+
this.defaultTimeout = (_options$timeout = options === null || options === void 0 ? void 0 : options.timeout) !== null && _options$timeout !== void 0 ? _options$timeout : DefaultTimeout.REQUEST;
|
|
86
|
+
this.defaultAsyncTimeout = (_options$asyncTimeout = options === null || options === void 0 ? void 0 : options.asyncTimeout) !== null && _options$asyncTimeout !== void 0 ? _options$asyncTimeout : DefaultTimeout.ASYNC;
|
|
87
|
+
|
|
88
|
+
// Set default returnData configuration
|
|
89
|
+
this.defaultReturnData = (_options$returnData = options === null || options === void 0 ? void 0 : options.returnData) !== null && _options$returnData !== void 0 ? _options$returnData : false;
|
|
90
|
+
|
|
91
|
+
// Save initial headers configuration
|
|
92
|
+
this.initialHeaders = options === null || options === void 0 ? void 0 : options.headers;
|
|
93
|
+
|
|
94
|
+
// Register stream message processing callback
|
|
95
|
+
this.server.setStreamCallback((data, context) => {
|
|
96
|
+
this.dispatchStreamMessage(data, context);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Register stream message handler (StreamMessageHandler interface implementation)
|
|
102
|
+
*/
|
|
103
|
+
registerStreamHandler(streamId, handler) {
|
|
104
|
+
this.streamHandlers.set(streamId, handler);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Unregister stream message handler (StreamMessageHandler interface implementation)
|
|
109
|
+
*/
|
|
110
|
+
unregisterStreamHandler(streamId) {
|
|
111
|
+
this.streamHandlers.delete(streamId);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
Send message (StreamMessageHandler interface implementation)
|
|
116
|
+
*/
|
|
117
|
+
postMessage(message) {
|
|
118
|
+
// Window check is handled in MessageDispatcher
|
|
119
|
+
this.server.messageDispatcher.send(this.targetWindow, message, this.targetOrigin);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Dispatch stream message to corresponding handler
|
|
124
|
+
*/
|
|
125
|
+
dispatchStreamMessage(data, context) {
|
|
126
|
+
// Validate origin for stream messages (stream_data/stream_end/stream_error/stream_cancel)
|
|
127
|
+
if (context) {
|
|
128
|
+
if (this.originValidator) {
|
|
129
|
+
try {
|
|
130
|
+
if (!this.originValidator(context.origin, data, context)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
} catch (_unused) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
} else if (this.targetOrigin !== OriginConstant.ANY && context.origin !== this.targetOrigin) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
var body = data.body;
|
|
141
|
+
if (!body || !body.streamId) return;
|
|
142
|
+
var handler = this.streamHandlers.get(body.streamId);
|
|
143
|
+
if (handler) {
|
|
144
|
+
if (context && !context.handledBy) {
|
|
145
|
+
context.accepted = true;
|
|
146
|
+
context.handledBy = this.id;
|
|
147
|
+
}
|
|
148
|
+
// Extract message type (remove stream_ prefix)
|
|
149
|
+
var messageType = data.type.replace('stream_', '');
|
|
150
|
+
handler(_objectSpread(_objectSpread({}, body), {}, {
|
|
151
|
+
type: messageType
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Resolve header value (handle function type headers)
|
|
158
|
+
*/
|
|
159
|
+
resolveHeaderValue(value, config) {
|
|
160
|
+
if (typeof value === 'function') {
|
|
161
|
+
return value(config);
|
|
162
|
+
}
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Detect Content-Type for request body
|
|
168
|
+
*/
|
|
169
|
+
detectContentTypeForBody(body) {
|
|
170
|
+
return detectContentType(body, {
|
|
171
|
+
checkStream: false
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Check if header exists (case-insensitive)
|
|
177
|
+
*/
|
|
178
|
+
hasHeader(headers, name) {
|
|
179
|
+
var lower = name.toLowerCase();
|
|
180
|
+
return Object.keys(headers).some(k => k.toLowerCase() === lower);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Merge and resolve headers (initial headers + request headers)
|
|
185
|
+
* Request headers take precedence over initial headers
|
|
186
|
+
* Also auto-detects and sets Content-Type if not already set
|
|
187
|
+
*/
|
|
188
|
+
mergeHeaders(config, body) {
|
|
189
|
+
var resolvedHeaders = {};
|
|
190
|
+
|
|
191
|
+
// First, resolve initial headers
|
|
192
|
+
if (this.initialHeaders) {
|
|
193
|
+
for (var _i = 0, _Object$entries = Object.entries(this.initialHeaders); _i < _Object$entries.length; _i++) {
|
|
194
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
195
|
+
key = _Object$entries$_i[0],
|
|
196
|
+
value = _Object$entries$_i[1];
|
|
197
|
+
resolvedHeaders[key] = this.resolveHeaderValue(value, config);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Then, merge request headers (request headers take precedence)
|
|
202
|
+
if (config.headers) {
|
|
203
|
+
for (var _i2 = 0, _Object$entries2 = Object.entries(config.headers); _i2 < _Object$entries2.length; _i2++) {
|
|
204
|
+
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
|
|
205
|
+
_key = _Object$entries2$_i[0],
|
|
206
|
+
_value = _Object$entries2$_i[1];
|
|
207
|
+
resolvedHeaders[_key] = this.resolveHeaderValue(_value, config);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Auto-detect and set Content-Type if not already set and body is provided
|
|
212
|
+
if (body !== undefined && !this.hasHeader(resolvedHeaders, HttpHeader.CONTENT_TYPE)) {
|
|
213
|
+
var contentType = this.detectContentTypeForBody(body);
|
|
214
|
+
if (contentType) {
|
|
215
|
+
resolvedHeaders[HttpHeader.CONTENT_TYPE] = contentType;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return resolvedHeaders;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Check if server is reachable
|
|
223
|
+
*/
|
|
224
|
+
isConnect() {
|
|
225
|
+
return new Promise((resolve, reject) => {
|
|
226
|
+
var requestId = generateRequestId();
|
|
227
|
+
var done = false;
|
|
228
|
+
var timeoutId = null;
|
|
229
|
+
var cleanup = () => {
|
|
230
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
231
|
+
this.server._unregisterPendingRequest(requestId);
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// Check if target window is still available before sending ping
|
|
235
|
+
if (!isWindowAvailable(this.targetWindow)) {
|
|
236
|
+
reject(new RequestIframeError({
|
|
237
|
+
message: Messages.TARGET_WINDOW_CLOSED,
|
|
238
|
+
code: ErrorCode.TARGET_WINDOW_CLOSED,
|
|
239
|
+
config: undefined,
|
|
240
|
+
requestId
|
|
241
|
+
}));
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
this.server._registerPendingRequest(requestId, data => {
|
|
245
|
+
if (done) return;
|
|
246
|
+
if (data.type === MessageType.ACK || data.type === MessageType.PONG) {
|
|
247
|
+
// Remember server's creatorId as target server ID for future requests
|
|
248
|
+
if (data.creatorId && !this._targetServerId) {
|
|
249
|
+
this._targetServerId = data.creatorId;
|
|
250
|
+
}
|
|
251
|
+
done = true;
|
|
252
|
+
cleanup();
|
|
253
|
+
resolve(true);
|
|
254
|
+
}
|
|
255
|
+
}, () => {
|
|
256
|
+
if (done) return;
|
|
257
|
+
done = true;
|
|
258
|
+
cleanup();
|
|
259
|
+
resolve(false);
|
|
260
|
+
}, this.targetOrigin, this.originValidator);
|
|
261
|
+
timeoutId = setTimeout(() => {
|
|
262
|
+
if (done) return;
|
|
263
|
+
done = true;
|
|
264
|
+
cleanup();
|
|
265
|
+
resolve(false);
|
|
266
|
+
}, this.defaultAckTimeout);
|
|
267
|
+
|
|
268
|
+
// Send ping via MessageDispatcher
|
|
269
|
+
this.server.messageDispatcher.sendMessage(this.targetWindow, this.targetOrigin, MessageType.PING, requestId, {
|
|
270
|
+
requireAck: true,
|
|
271
|
+
targetId: this._targetServerId
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
send(path, body, options) {
|
|
276
|
+
var _this = this;
|
|
277
|
+
return _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
278
|
+
var config, processedConfig, processedBody, mergedHeaders, processedPath, processedCookies, userTargetId, _processedConfig$requ, requestId, targetId;
|
|
279
|
+
return _regeneratorRuntime.wrap(function (_context) {
|
|
280
|
+
while (1) switch (_context.prev = _context.next) {
|
|
281
|
+
case 0:
|
|
282
|
+
config = _objectSpread({
|
|
283
|
+
path,
|
|
284
|
+
body
|
|
285
|
+
}, options);
|
|
286
|
+
_context.next = 1;
|
|
287
|
+
return runRequestInterceptors(_this.interceptors.request, config);
|
|
288
|
+
case 1:
|
|
289
|
+
processedConfig = _context.sent;
|
|
290
|
+
processedBody = processedConfig.body; // Universal send: dispatch by type (like response.send)
|
|
291
|
+
if (!(typeof File !== 'undefined' && processedBody instanceof File || typeof Blob !== 'undefined' && processedBody instanceof Blob)) {
|
|
292
|
+
_context.next = 2;
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
return _context.abrupt("return", _this.sendFile(path, processedBody, options));
|
|
296
|
+
case 2:
|
|
297
|
+
if (!isIframeWritableStream(processedBody)) {
|
|
298
|
+
_context.next = 3;
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
return _context.abrupt("return", _this.sendStream(path, processedBody, options));
|
|
302
|
+
case 3:
|
|
303
|
+
// Merge and resolve headers (initial headers + request headers)
|
|
304
|
+
mergedHeaders = _this.mergeHeaders(processedConfig, processedBody);
|
|
305
|
+
processedPath = processedConfig.path, processedCookies = processedConfig.cookies, userTargetId = processedConfig.targetId, _processedConfig$requ = processedConfig.requestId, requestId = _processedConfig$requ === void 0 ? generateRequestId() : _processedConfig$requ;
|
|
306
|
+
targetId = userTargetId || _this._targetServerId;
|
|
307
|
+
return _context.abrupt("return", _this._sendRequest(processedPath, processedBody, mergedHeaders, processedCookies, processedConfig, requestId, targetId));
|
|
308
|
+
case 4:
|
|
309
|
+
case "end":
|
|
310
|
+
return _context.stop();
|
|
311
|
+
}
|
|
312
|
+
}, _callee);
|
|
313
|
+
}))();
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Send file as request body (stream only; server receives stream or auto-resolved File/Blob via autoResolve).
|
|
318
|
+
*/
|
|
319
|
+
sendFile(path, content, options) {
|
|
320
|
+
var _this2 = this;
|
|
321
|
+
return _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
|
|
322
|
+
var _options$autoResolve;
|
|
323
|
+
var streamAutoResolve, mimeType, fileName, _yield$import, IframeFileWritableStream, fileStream;
|
|
324
|
+
return _regeneratorRuntime.wrap(function (_context3) {
|
|
325
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
326
|
+
case 0:
|
|
327
|
+
streamAutoResolve = (_options$autoResolve = options === null || options === void 0 ? void 0 : options.autoResolve) !== null && _options$autoResolve !== void 0 ? _options$autoResolve : true;
|
|
328
|
+
mimeType = options === null || options === void 0 ? void 0 : options.mimeType;
|
|
329
|
+
fileName = options === null || options === void 0 ? void 0 : options.fileName;
|
|
330
|
+
_context3.next = 1;
|
|
331
|
+
return import('../stream');
|
|
332
|
+
case 1:
|
|
333
|
+
_yield$import = _context3.sent;
|
|
334
|
+
IframeFileWritableStream = _yield$import.IframeFileWritableStream;
|
|
335
|
+
fileStream = new IframeFileWritableStream({
|
|
336
|
+
filename: fileName || (typeof File !== 'undefined' && content instanceof File ? content.name : 'file'),
|
|
337
|
+
mimeType: mimeType || (typeof File !== 'undefined' && content instanceof File ? content.type : content === null || content === void 0 ? void 0 : content.type) || 'application/octet-stream',
|
|
338
|
+
chunked: false,
|
|
339
|
+
autoResolve: streamAutoResolve,
|
|
340
|
+
next: function () {
|
|
341
|
+
var _next = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
|
|
342
|
+
var data, _t;
|
|
343
|
+
return _regeneratorRuntime.wrap(function (_context2) {
|
|
344
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
345
|
+
case 0:
|
|
346
|
+
if (!(typeof content === 'string')) {
|
|
347
|
+
_context2.next = 1;
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
_t = btoa(unescape(encodeURIComponent(content)));
|
|
351
|
+
_context2.next = 3;
|
|
352
|
+
break;
|
|
353
|
+
case 1:
|
|
354
|
+
_context2.next = 2;
|
|
355
|
+
return blobToBase64(content);
|
|
356
|
+
case 2:
|
|
357
|
+
_t = _context2.sent;
|
|
358
|
+
case 3:
|
|
359
|
+
data = _t;
|
|
360
|
+
return _context2.abrupt("return", {
|
|
361
|
+
data,
|
|
362
|
+
done: true
|
|
363
|
+
});
|
|
364
|
+
case 4:
|
|
365
|
+
case "end":
|
|
366
|
+
return _context2.stop();
|
|
367
|
+
}
|
|
368
|
+
}, _callee2);
|
|
369
|
+
}));
|
|
370
|
+
function next() {
|
|
371
|
+
return _next.apply(this, arguments);
|
|
372
|
+
}
|
|
373
|
+
return next;
|
|
374
|
+
}()
|
|
375
|
+
});
|
|
376
|
+
return _context3.abrupt("return", _this2.sendStream(path, fileStream, options));
|
|
377
|
+
case 2:
|
|
378
|
+
case "end":
|
|
379
|
+
return _context3.stop();
|
|
380
|
+
}
|
|
381
|
+
}, _callee3);
|
|
382
|
+
}))();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Send stream as request body (server receives readable stream).
|
|
387
|
+
* Sends REQUEST with streamId and stream: true, then starts the writable stream.
|
|
388
|
+
*/
|
|
389
|
+
sendStream(path, stream, options) {
|
|
390
|
+
var _this3 = this;
|
|
391
|
+
return _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
|
|
392
|
+
var _processedConfig$requ2, _processedConfig$targ;
|
|
393
|
+
var config, processedConfig, requestId, targetId, processedPath, mergedHeaders, pathMatchedCookies, mergedCookies, streamConfig, promise;
|
|
394
|
+
return _regeneratorRuntime.wrap(function (_context4) {
|
|
395
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
396
|
+
case 0:
|
|
397
|
+
config = _objectSpread({
|
|
398
|
+
path,
|
|
399
|
+
body: undefined
|
|
400
|
+
}, options);
|
|
401
|
+
_context4.next = 1;
|
|
402
|
+
return runRequestInterceptors(_this3.interceptors.request, config);
|
|
403
|
+
case 1:
|
|
404
|
+
processedConfig = _context4.sent;
|
|
405
|
+
requestId = (_processedConfig$requ2 = processedConfig.requestId) !== null && _processedConfig$requ2 !== void 0 ? _processedConfig$requ2 : generateRequestId();
|
|
406
|
+
targetId = (_processedConfig$targ = processedConfig.targetId) !== null && _processedConfig$targ !== void 0 ? _processedConfig$targ : _this3._targetServerId;
|
|
407
|
+
processedPath = processedConfig.path;
|
|
408
|
+
stream._bind({
|
|
409
|
+
requestId,
|
|
410
|
+
targetWindow: _this3.targetWindow,
|
|
411
|
+
targetOrigin: _this3.targetOrigin,
|
|
412
|
+
secretKey: _this3.secretKey,
|
|
413
|
+
channel: _this3.server.messageDispatcher.getChannel(),
|
|
414
|
+
registerStreamHandler: _this3.registerStreamHandler.bind(_this3),
|
|
415
|
+
unregisterStreamHandler: _this3.unregisterStreamHandler.bind(_this3),
|
|
416
|
+
heartbeat: () => _this3.isConnect(),
|
|
417
|
+
clientId: _this3.id,
|
|
418
|
+
targetId
|
|
419
|
+
});
|
|
420
|
+
mergedHeaders = _this3.mergeHeaders(processedConfig, undefined);
|
|
421
|
+
pathMatchedCookies = _this3._cookieStore.getForPath(processedPath);
|
|
422
|
+
mergedCookies = _objectSpread(_objectSpread({}, pathMatchedCookies), processedConfig.cookies);
|
|
423
|
+
streamConfig = _objectSpread(_objectSpread({}, processedConfig), {}, {
|
|
424
|
+
requestId
|
|
425
|
+
});
|
|
426
|
+
promise = _this3._sendRequest(processedPath, undefined, mergedHeaders, mergedCookies, streamConfig, requestId, targetId, {
|
|
427
|
+
streamId: stream.streamId
|
|
428
|
+
});
|
|
429
|
+
/** Start stream after REQUEST is sent (_sendRequest sends synchronously in executor) */
|
|
430
|
+
void stream.start();
|
|
431
|
+
return _context4.abrupt("return", promise);
|
|
432
|
+
case 2:
|
|
433
|
+
case "end":
|
|
434
|
+
return _context4.stop();
|
|
435
|
+
}
|
|
436
|
+
}, _callee4);
|
|
437
|
+
}))();
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Internal: send REQUEST and wait for response (used by send, sendFile, sendStream).
|
|
442
|
+
*/
|
|
443
|
+
_sendRequest(requestPath, body, mergedHeaders, processedCookies, processedConfig, requestId, targetId, extraPayload) {
|
|
444
|
+
var _processedConfig$ackT = processedConfig.ackTimeout,
|
|
445
|
+
ackTimeout = _processedConfig$ackT === void 0 ? this.defaultAckTimeout : _processedConfig$ackT,
|
|
446
|
+
_processedConfig$time = processedConfig.timeout,
|
|
447
|
+
timeout = _processedConfig$time === void 0 ? this.defaultTimeout : _processedConfig$time,
|
|
448
|
+
_processedConfig$asyn = processedConfig.asyncTimeout,
|
|
449
|
+
asyncTimeout = _processedConfig$asyn === void 0 ? this.defaultAsyncTimeout : _processedConfig$asyn,
|
|
450
|
+
_processedConfig$requ3 = processedConfig.requireAck,
|
|
451
|
+
requireAck = _processedConfig$requ3 === void 0 ? true : _processedConfig$requ3,
|
|
452
|
+
streamTimeout = processedConfig.streamTimeout,
|
|
453
|
+
ack = processedConfig.ack,
|
|
454
|
+
_processedConfig$retu = processedConfig.returnData,
|
|
455
|
+
returnData = _processedConfig$retu === void 0 ? this.defaultReturnData : _processedConfig$retu;
|
|
456
|
+
return new Promise((resolve, reject) => {
|
|
457
|
+
var done = false;
|
|
458
|
+
var timeoutId = null;
|
|
459
|
+
var cleanup = () => {
|
|
460
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
461
|
+
this.server._unregisterPendingRequest(requestId);
|
|
462
|
+
};
|
|
463
|
+
var fail = error => {
|
|
464
|
+
if (done) return;
|
|
465
|
+
done = true;
|
|
466
|
+
cleanup();
|
|
467
|
+
// Convert to RequestIframeError instance
|
|
468
|
+
var errorInstance = error instanceof RequestIframeError ? error : new RequestIframeError(error);
|
|
469
|
+
// Run response interceptors to allow error logging
|
|
470
|
+
Promise.reject(errorInstance).catch(err => {
|
|
471
|
+
// Run through response interceptors' rejected callbacks
|
|
472
|
+
var promise = Promise.reject(err);
|
|
473
|
+
this.interceptors.response.forEach(interceptor => {
|
|
474
|
+
promise = promise.catch(e => {
|
|
475
|
+
if (interceptor.rejected) {
|
|
476
|
+
return interceptor.rejected(e);
|
|
477
|
+
}
|
|
478
|
+
return Promise.reject(e);
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
return promise;
|
|
482
|
+
}).catch(() => {
|
|
483
|
+
// After interceptors, reject with original error
|
|
484
|
+
reject(errorInstance);
|
|
485
|
+
});
|
|
486
|
+
};
|
|
487
|
+
var setAckTimeout = () => {
|
|
488
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
489
|
+
timeoutId = setTimeout(() => {
|
|
490
|
+
fail(new RequestIframeError({
|
|
491
|
+
message: formatMessage(Messages.ACK_TIMEOUT, ackTimeout),
|
|
492
|
+
code: ErrorCode.ACK_TIMEOUT,
|
|
493
|
+
config: processedConfig,
|
|
494
|
+
requestId
|
|
495
|
+
}));
|
|
496
|
+
}, ackTimeout);
|
|
497
|
+
};
|
|
498
|
+
var setRequestTimeout = () => {
|
|
499
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
500
|
+
timeoutId = setTimeout(() => {
|
|
501
|
+
fail(new RequestIframeError({
|
|
502
|
+
message: formatMessage(Messages.REQUEST_TIMEOUT, timeout),
|
|
503
|
+
code: ErrorCode.TIMEOUT,
|
|
504
|
+
config: processedConfig,
|
|
505
|
+
requestId
|
|
506
|
+
}));
|
|
507
|
+
}, timeout);
|
|
508
|
+
};
|
|
509
|
+
var setAsyncTimeout = () => {
|
|
510
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
511
|
+
timeoutId = setTimeout(() => {
|
|
512
|
+
fail(new RequestIframeError({
|
|
513
|
+
message: formatMessage(Messages.ASYNC_REQUEST_TIMEOUT, asyncTimeout),
|
|
514
|
+
code: ErrorCode.ASYNC_TIMEOUT,
|
|
515
|
+
config: processedConfig,
|
|
516
|
+
requestId
|
|
517
|
+
}));
|
|
518
|
+
}, asyncTimeout);
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
// Register to server's pending requests
|
|
522
|
+
this.server._registerPendingRequest(requestId, data => {
|
|
523
|
+
if (done) return;
|
|
524
|
+
|
|
525
|
+
// Received ACK: server has received request
|
|
526
|
+
if (data.type === MessageType.ACK) {
|
|
527
|
+
// Optional ack match (ignore mismatched ACK)
|
|
528
|
+
if (ack !== undefined && !isAckMatch(ack, data.ack)) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
// Remember server's creatorId as target server ID for future requests
|
|
532
|
+
if (data.creatorId && !this._targetServerId) {
|
|
533
|
+
this._targetServerId = data.creatorId;
|
|
534
|
+
}
|
|
535
|
+
// Switch to request timeout
|
|
536
|
+
setRequestTimeout();
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Received ASYNC notification: this is an async task
|
|
541
|
+
if (data.type === MessageType.ASYNC) {
|
|
542
|
+
// Remember server's creatorId as target server ID for future requests
|
|
543
|
+
if (data.creatorId && !this._targetServerId) {
|
|
544
|
+
this._targetServerId = data.creatorId;
|
|
545
|
+
}
|
|
546
|
+
// Switch to async timeout
|
|
547
|
+
setAsyncTimeout();
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// Received stream start message
|
|
552
|
+
if (data.type === MessageType.STREAM_START) {
|
|
553
|
+
var _streamBody$chunked, _streamBody$autoResol;
|
|
554
|
+
done = true;
|
|
555
|
+
cleanup();
|
|
556
|
+
var streamBody = data.body;
|
|
557
|
+
var streamId = streamBody.streamId;
|
|
558
|
+
var streamType = streamBody.type || StreamTypeConstant.DATA;
|
|
559
|
+
var streamMode = streamBody.mode;
|
|
560
|
+
var streamChunked = (_streamBody$chunked = streamBody.chunked) !== null && _streamBody$chunked !== void 0 ? _streamBody$chunked : true;
|
|
561
|
+
var streamMetadata = streamBody.metadata;
|
|
562
|
+
var autoResolve = (_streamBody$autoResol = streamBody.autoResolve) !== null && _streamBody$autoResol !== void 0 ? _streamBody$autoResol : false;
|
|
563
|
+
|
|
564
|
+
// Create corresponding readable stream based on stream type
|
|
565
|
+
if (streamType === StreamTypeConstant.FILE) {
|
|
566
|
+
var _readableStream = new IframeFileReadableStream(streamId, requestId, this, {
|
|
567
|
+
chunked: streamChunked,
|
|
568
|
+
metadata: streamMetadata,
|
|
569
|
+
secretKey: this.secretKey,
|
|
570
|
+
idleTimeout: streamTimeout,
|
|
571
|
+
heartbeat: () => this.isConnect(),
|
|
572
|
+
mode: streamMode,
|
|
573
|
+
filename: streamMetadata === null || streamMetadata === void 0 ? void 0 : streamMetadata.filename,
|
|
574
|
+
mimeType: streamMetadata === null || streamMetadata === void 0 ? void 0 : streamMetadata.mimeType,
|
|
575
|
+
size: streamMetadata === null || streamMetadata === void 0 ? void 0 : streamMetadata.size
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
// If autoResolve is enabled, automatically read and convert to File/Blob
|
|
579
|
+
if (autoResolve) {
|
|
580
|
+
var _data$headers;
|
|
581
|
+
// Extract fileName from headers if available
|
|
582
|
+
var contentDisposition = (_data$headers = data.headers) === null || _data$headers === void 0 ? void 0 : _data$headers[HttpHeader.CONTENT_DISPOSITION];
|
|
583
|
+
var fileName;
|
|
584
|
+
if (contentDisposition) {
|
|
585
|
+
var disposition = typeof contentDisposition === 'string' ? contentDisposition : contentDisposition[0];
|
|
586
|
+
var filenameMatch = disposition.match(/filename="?([^"]+)"?/i);
|
|
587
|
+
if (filenameMatch) {
|
|
588
|
+
fileName = filenameMatch[1];
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
// Fallback to stream metadata if not found in headers
|
|
592
|
+
fileName = fileName || (streamMetadata === null || streamMetadata === void 0 ? void 0 : streamMetadata.filename) || _readableStream.filename;
|
|
593
|
+
|
|
594
|
+
// Use stream's readAsFile or readAsBlob method
|
|
595
|
+
var fileDataPromise = fileName ? _readableStream.readAsFile(fileName) : _readableStream.readAsBlob();
|
|
596
|
+
fileDataPromise.then(fileData => {
|
|
597
|
+
var resp = {
|
|
598
|
+
data: fileData,
|
|
599
|
+
status: data.status || HttpStatus.OK,
|
|
600
|
+
statusText: data.statusText || HttpStatusText[HttpStatus.OK],
|
|
601
|
+
requestId,
|
|
602
|
+
headers: data.headers
|
|
603
|
+
};
|
|
604
|
+
return runResponseInterceptors(this.interceptors.response, resp);
|
|
605
|
+
}).then(response => {
|
|
606
|
+
resolve(returnData ? response.data : response);
|
|
607
|
+
}).catch(reject);
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// Non-autoResolve: return file stream directly
|
|
612
|
+
var _resp = {
|
|
613
|
+
data: undefined,
|
|
614
|
+
status: data.status || HttpStatus.OK,
|
|
615
|
+
statusText: data.statusText || HttpStatusText[HttpStatus.OK],
|
|
616
|
+
requestId,
|
|
617
|
+
headers: data.headers,
|
|
618
|
+
stream: _readableStream
|
|
619
|
+
};
|
|
620
|
+
runResponseInterceptors(this.interceptors.response, _resp).then(response => {
|
|
621
|
+
resolve(returnData ? response.data : response);
|
|
622
|
+
}).catch(reject);
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// Non-file stream: create regular readable stream
|
|
627
|
+
var readableStream = new IframeReadableStream(streamId, requestId, this, {
|
|
628
|
+
type: streamType,
|
|
629
|
+
mode: streamMode,
|
|
630
|
+
chunked: streamChunked,
|
|
631
|
+
metadata: streamMetadata,
|
|
632
|
+
secretKey: this.secretKey,
|
|
633
|
+
idleTimeout: streamTimeout,
|
|
634
|
+
heartbeat: () => this.isConnect()
|
|
635
|
+
});
|
|
636
|
+
var resp = {
|
|
637
|
+
data: undefined,
|
|
638
|
+
status: data.status || HttpStatus.OK,
|
|
639
|
+
statusText: data.statusText || HttpStatusText[HttpStatus.OK],
|
|
640
|
+
requestId,
|
|
641
|
+
headers: data.headers,
|
|
642
|
+
stream: readableStream
|
|
643
|
+
};
|
|
644
|
+
runResponseInterceptors(this.interceptors.response, resp).then(response => {
|
|
645
|
+
resolve(returnData ? response.data : response);
|
|
646
|
+
}).catch(reject);
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// Received stream data/end/error/cancel message - dispatch to stream handler
|
|
651
|
+
if (data.type.startsWith('stream_')) {
|
|
652
|
+
this.dispatchStreamMessage(data);
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// Received response
|
|
657
|
+
if (data.type === MessageType.RESPONSE) {
|
|
658
|
+
done = true;
|
|
659
|
+
cleanup();
|
|
660
|
+
|
|
661
|
+
// Remember server's creatorId as target server ID for future requests
|
|
662
|
+
if (data.creatorId && !this._targetServerId) {
|
|
663
|
+
this._targetServerId = data.creatorId;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// Parse and save server-set cookies (from Set-Cookie header)
|
|
667
|
+
if (data.headers && data.headers[HttpHeader.SET_COOKIE]) {
|
|
668
|
+
var setCookies = data.headers[HttpHeader.SET_COOKIE];
|
|
669
|
+
var setCookieArray = Array.isArray(setCookies) ? setCookies : [setCookies];
|
|
670
|
+
var _iterator = _createForOfIteratorHelper(setCookieArray),
|
|
671
|
+
_step;
|
|
672
|
+
try {
|
|
673
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
674
|
+
var setCookieStr = _step.value;
|
|
675
|
+
this._cookieStore.setFromSetCookie(setCookieStr);
|
|
676
|
+
}
|
|
677
|
+
} catch (err) {
|
|
678
|
+
_iterator.e(err);
|
|
679
|
+
} finally {
|
|
680
|
+
_iterator.f();
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
var _resp2 = {
|
|
684
|
+
data: data.data,
|
|
685
|
+
status: data.status || HttpStatus.OK,
|
|
686
|
+
statusText: data.statusText || HttpStatusText[HttpStatus.OK],
|
|
687
|
+
requestId,
|
|
688
|
+
headers: data.headers
|
|
689
|
+
};
|
|
690
|
+
runResponseInterceptors(this.interceptors.response, _resp2).then(response => {
|
|
691
|
+
resolve(returnData ? response.data : response);
|
|
692
|
+
}).catch(reject);
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// Received error
|
|
697
|
+
if (data.type === MessageType.ERROR) {
|
|
698
|
+
var _data$error, _data$error2;
|
|
699
|
+
// Remember server's creatorId as target server ID for future requests
|
|
700
|
+
if (data.creatorId && !this._targetServerId) {
|
|
701
|
+
this._targetServerId = data.creatorId;
|
|
702
|
+
}
|
|
703
|
+
fail(new RequestIframeError({
|
|
704
|
+
message: ((_data$error = data.error) === null || _data$error === void 0 ? void 0 : _data$error.message) || Messages.REQUEST_FAILED,
|
|
705
|
+
code: ((_data$error2 = data.error) === null || _data$error2 === void 0 ? void 0 : _data$error2.code) || ErrorCode.REQUEST_ERROR,
|
|
706
|
+
config: processedConfig,
|
|
707
|
+
response: data.status ? {
|
|
708
|
+
data: data.data,
|
|
709
|
+
status: data.status,
|
|
710
|
+
statusText: data.statusText || Messages.ERROR
|
|
711
|
+
} : undefined,
|
|
712
|
+
requestId
|
|
713
|
+
}));
|
|
714
|
+
}
|
|
715
|
+
}, error => {
|
|
716
|
+
fail(new RequestIframeError({
|
|
717
|
+
message: error.message || Messages.REQUEST_FAILED,
|
|
718
|
+
code: ErrorCode.REQUEST_ERROR,
|
|
719
|
+
config: processedConfig,
|
|
720
|
+
requestId
|
|
721
|
+
}));
|
|
722
|
+
}, this.targetOrigin, this.originValidator);
|
|
723
|
+
|
|
724
|
+
// Set ACK timeout (delivery stage). If disabled, start request timeout immediately.
|
|
725
|
+
if (requireAck === false) {
|
|
726
|
+
setRequestTimeout();
|
|
727
|
+
} else {
|
|
728
|
+
setAckTimeout();
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// Get cookies matching request path and merge with user-provided cookies (user-provided takes precedence)
|
|
732
|
+
var pathMatchedCookies = this._cookieStore.getForPath(requestPath);
|
|
733
|
+
var mergedCookies = _objectSpread(_objectSpread({}, pathMatchedCookies), processedCookies);
|
|
734
|
+
|
|
735
|
+
// Send request via MessageDispatcher
|
|
736
|
+
var payload = {
|
|
737
|
+
path: requestPath,
|
|
738
|
+
body,
|
|
739
|
+
headers: mergedHeaders,
|
|
740
|
+
cookies: mergedCookies,
|
|
741
|
+
targetId,
|
|
742
|
+
requireAck,
|
|
743
|
+
ack
|
|
744
|
+
};
|
|
745
|
+
if (extraPayload !== null && extraPayload !== void 0 && extraPayload.streamId) {
|
|
746
|
+
payload.streamId = extraPayload.streamId;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// Check if target window is still available before sending
|
|
750
|
+
if (!isWindowAvailable(this.targetWindow)) {
|
|
751
|
+
fail(new RequestIframeError({
|
|
752
|
+
message: Messages.TARGET_WINDOW_CLOSED,
|
|
753
|
+
code: ErrorCode.TARGET_WINDOW_CLOSED,
|
|
754
|
+
config: processedConfig,
|
|
755
|
+
requestId
|
|
756
|
+
}));
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
this.server.messageDispatcher.sendMessage(this.targetWindow, this.targetOrigin, MessageType.REQUEST, requestId, payload);
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Get internal server instance (for debugging)
|
|
764
|
+
*/
|
|
765
|
+
getServer() {
|
|
766
|
+
return this.server;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Whether message handling is enabled
|
|
771
|
+
*/
|
|
772
|
+
get isOpen() {
|
|
773
|
+
return this.server.isOpen;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* Check if target window is still available (not closed/removed)
|
|
778
|
+
* @returns true if target window is available, false otherwise
|
|
779
|
+
*/
|
|
780
|
+
isAvailable() {
|
|
781
|
+
return isWindowAvailable(this.targetWindow);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Enable message handling (register message handlers)
|
|
786
|
+
*/
|
|
787
|
+
open() {
|
|
788
|
+
this.server.open();
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* Disable message handling (unregister message handlers, but don't release resources)
|
|
793
|
+
*/
|
|
794
|
+
close() {
|
|
795
|
+
this.server.close();
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* Destroy client (close and release all resources)
|
|
800
|
+
*/
|
|
801
|
+
destroy() {
|
|
802
|
+
// Clear cookies
|
|
803
|
+
this._cookieStore.clear();
|
|
804
|
+
|
|
805
|
+
// Clear stream handlers
|
|
806
|
+
this.streamHandlers.clear();
|
|
807
|
+
|
|
808
|
+
// Clear interceptors
|
|
809
|
+
this.interceptors.request.clear();
|
|
810
|
+
this.interceptors.response.clear();
|
|
811
|
+
|
|
812
|
+
// Destroy server (this will also release the message channel)
|
|
813
|
+
this.server.destroy();
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/**
|
|
817
|
+
* Get all cookies matching specified path
|
|
818
|
+
* @param path Request path, returns all cookies if not provided
|
|
819
|
+
*/
|
|
820
|
+
getCookies(path) {
|
|
821
|
+
if (path) {
|
|
822
|
+
return this._cookieStore.getForPath(path);
|
|
823
|
+
}
|
|
824
|
+
return this._cookieStore.getAllSimple();
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* Get specified cookie
|
|
829
|
+
* @param name Cookie name
|
|
830
|
+
* @param path Path (optional)
|
|
831
|
+
*/
|
|
832
|
+
getCookie(name, path) {
|
|
833
|
+
return this._cookieStore.get(name, path);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* Set cookie
|
|
838
|
+
* @param name Cookie name
|
|
839
|
+
* @param value Cookie value
|
|
840
|
+
* @param options Cookie options (path, etc.)
|
|
841
|
+
*/
|
|
842
|
+
setCookie(name, value, options) {
|
|
843
|
+
var _options$path;
|
|
844
|
+
var expires;
|
|
845
|
+
if (options !== null && options !== void 0 && options.expires) {
|
|
846
|
+
expires = options.expires.getTime();
|
|
847
|
+
} else if ((options === null || options === void 0 ? void 0 : options.maxAge) !== undefined) {
|
|
848
|
+
expires = Date.now() + options.maxAge * 1000;
|
|
849
|
+
}
|
|
850
|
+
this._cookieStore.set({
|
|
851
|
+
name,
|
|
852
|
+
value,
|
|
853
|
+
path: (_options$path = options === null || options === void 0 ? void 0 : options.path) !== null && _options$path !== void 0 ? _options$path : '/',
|
|
854
|
+
expires
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* Remove specified cookie
|
|
860
|
+
* @param name Cookie name
|
|
861
|
+
* @param path Path (optional, defaults to '/')
|
|
862
|
+
*/
|
|
863
|
+
removeCookie(name, path) {
|
|
864
|
+
this._cookieStore.remove(name, path !== null && path !== void 0 ? path : '/');
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
/**
|
|
868
|
+
* Clear all cookies
|
|
869
|
+
*/
|
|
870
|
+
clearCookies() {
|
|
871
|
+
this._cookieStore.clear();
|
|
872
|
+
}
|
|
873
|
+
}
|