react-native-blob-util 0.19.0 → 0.19.2

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.
Files changed (91) hide show
  1. package/.eslintrc.js +56 -56
  2. package/LICENSE +21 -21
  3. package/Migration.md +41 -41
  4. package/README.md +1071 -1071
  5. package/android/gradle.properties +1 -1
  6. package/android/proguard-rules.pro +17 -17
  7. package/android/src/main/AndroidManifest.xml +39 -40
  8. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilConfig.java +57 -57
  9. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilConst.java +20 -20
  10. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFS.java +2 -2
  11. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFileTransformer.java +9 -9
  12. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilImpl.java +431 -431
  13. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilProgressConfig.java +39 -39
  14. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilReq.java +972 -968
  15. package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilDefaultResp.java +98 -98
  16. package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilFileResp.java +157 -157
  17. package/android/src/main/java/com/ReactNativeBlobUtil/Utils/FileDescription.java +19 -19
  18. package/android/src/main/java/com/ReactNativeBlobUtil/Utils/FileProvider.java +4 -4
  19. package/android/src/main/java/com/ReactNativeBlobUtil/Utils/MimeType.java +70 -70
  20. package/android/src/main/java/com/ReactNativeBlobUtil/Utils/PathResolver.java +223 -223
  21. package/android/src/main/java/com/ReactNativeBlobUtil/Utils/Tls12SocketFactory.java +68 -68
  22. package/android/src/main/res/values/strings.xml +3 -3
  23. package/android/src/main/res/xml/provider_paths.xml +12 -12
  24. package/android/src/newarch/java/com/ReactNativeBlobUtil/ReactNativeBlobUtil.java +1 -1
  25. package/android.js +58 -58
  26. package/class/ReactNativeBlobUtilCanceledFetchError.js +9 -9
  27. package/class/ReactNativeBlobUtilFile.js +5 -5
  28. package/class/ReactNativeBlobUtilReadStream.js +84 -84
  29. package/class/ReactNativeBlobUtilSession.js +68 -68
  30. package/class/ReactNativeBlobUtilWriteStream.js +50 -50
  31. package/class/StatefulPromise.js +7 -7
  32. package/codegenSpecs/NativeBlobUtils.js +86 -82
  33. package/components/Fetch.onPress.js +10 -10
  34. package/components/Fetch.when.js +15 -15
  35. package/fetch.js +344 -344
  36. package/fs.js +480 -480
  37. package/index.d.ts +871 -871
  38. package/index.js +64 -64
  39. package/index.js.flow +191 -191
  40. package/index.web.js +1 -1
  41. package/ios/ReactNativeBlobUtil/ReactNativeBlobUtil.h +55 -55
  42. package/ios/ReactNativeBlobUtil/ReactNativeBlobUtil.mm +993 -993
  43. package/ios/ReactNativeBlobUtil.xcodeproj/project.pbxproj +403 -403
  44. package/ios/ReactNativeBlobUtilConst.h +58 -58
  45. package/ios/ReactNativeBlobUtilConst.mm +47 -47
  46. package/ios/ReactNativeBlobUtilFS.h +108 -108
  47. package/ios/ReactNativeBlobUtilFS.mm +977 -977
  48. package/ios/ReactNativeBlobUtilFileTransformer.h +23 -23
  49. package/ios/ReactNativeBlobUtilFileTransformer.mm +20 -20
  50. package/ios/ReactNativeBlobUtilNetwork.h +49 -49
  51. package/ios/ReactNativeBlobUtilNetwork.mm +159 -159
  52. package/ios/ReactNativeBlobUtilProgress.h +32 -32
  53. package/ios/ReactNativeBlobUtilProgress.mm +57 -57
  54. package/ios/ReactNativeBlobUtilReqBuilder.h +37 -37
  55. package/ios/ReactNativeBlobUtilReqBuilder.mm +292 -292
  56. package/ios/ReactNativeBlobUtilRequest.h +48 -48
  57. package/ios/ReactNativeBlobUtilRequest.mm +535 -535
  58. package/ios.js +61 -61
  59. package/json-stream.js +42 -42
  60. package/lib/oboe-browser.js +2703 -2703
  61. package/mediacollection.js +36 -36
  62. package/package.json +55 -55
  63. package/polyfill/Blob.js +362 -362
  64. package/polyfill/Event.js +11 -11
  65. package/polyfill/EventTarget.js +78 -78
  66. package/polyfill/Fetch.js +219 -219
  67. package/polyfill/File.js +27 -27
  68. package/polyfill/FileReader.js +91 -91
  69. package/polyfill/ProgressEvent.js +32 -32
  70. package/polyfill/XMLHttpRequest.js +466 -466
  71. package/polyfill/XMLHttpRequestEventTarget.js +126 -126
  72. package/polyfill/index.js +11 -11
  73. package/react-native-blob-util.podspec +45 -45
  74. package/types.js +69 -69
  75. package/utils/log.js +40 -40
  76. package/utils/unicode.js +7 -7
  77. package/utils/uri.js +33 -33
  78. package/utils/uuid.js +4 -4
  79. package/windows/README.md +2 -2
  80. package/windows/ReactNativeBlobUtil/PropertySheet.props +15 -15
  81. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.cpp +1701 -1693
  82. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.def +3 -3
  83. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.h +379 -366
  84. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.vcxproj +181 -181
  85. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.vcxproj.filters +31 -31
  86. package/windows/ReactNativeBlobUtil/ReactPackageProvider.cpp +15 -15
  87. package/windows/ReactNativeBlobUtil/ReactPackageProvider.h +20 -20
  88. package/windows/ReactNativeBlobUtil/ReactPackageProvider.idl +9 -9
  89. package/windows/ReactNativeBlobUtil/packages.config +3 -3
  90. package/windows/ReactNativeBlobUtil/pch.cpp +1 -1
  91. package/windows/ReactNativeBlobUtil/pch.h +3 -3
@@ -1,466 +1,466 @@
1
- // Copyright 2016 wkh237@github. All rights reserved.
2
- // Use of this source code is governed by a MIT-style license that can be
3
- // found in the LICENSE file.
4
-
5
- import XMLHttpRequestEventTarget from './XMLHttpRequestEventTarget.js';
6
- import Log from '../utils/log.js';
7
- import Blob from './Blob.js';
8
- import ProgressEvent from './ProgressEvent.js';
9
- import URIUtil from "../utils/uri";
10
- import {config} from "../fetch";
11
-
12
- const log = new Log('XMLHttpRequest');
13
-
14
-
15
- log.disable();
16
- // log.level(3)
17
-
18
- const UNSENT = 0;
19
- const OPENED = 1;
20
- const HEADERS_RECEIVED = 2;
21
- const LOADING = 3;
22
- const DONE = 4;
23
-
24
- export default class XMLHttpRequest extends XMLHttpRequestEventTarget {
25
-
26
- _onreadystatechange: () => void;
27
-
28
- upload: XMLHttpRequestEventTarget = new XMLHttpRequestEventTarget();
29
- static binaryContentTypes: Array<string> = [
30
- 'image/', 'video/', 'audio/'
31
- ];
32
-
33
- // readonly
34
- _readyState: number = UNSENT;
35
- _uriType: 'net' | 'file' = 'net';
36
- _response: any = '';
37
- _responseText: any = '';
38
- _responseHeaders: any = {};
39
- _responseType: '' | 'arraybuffer' | 'blob' | 'json' | 'text' = '';
40
- // TODO : not suppoted ATM
41
- _responseURL: null = '';
42
- _responseXML: null = '';
43
- _status: number = 0;
44
- _statusText: string = '';
45
- _timeout: number = 60000;
46
- _sendFlag: boolean = false;
47
- _uploadStarted: boolean = false;
48
- _increment: boolean = false;
49
-
50
- // ReactNativeBlobUtil compatible data structure
51
- _config: ReactNativeBlobUtilConfig = {};
52
- _url: any;
53
- _method: string;
54
- _headers: any = {
55
- 'Content-Type': 'text/plain'
56
- };
57
- _cleanUp: () => void = null;
58
- _body: any;
59
-
60
- // ReactNativeBlobUtil promise object, which has `progress`, `uploadProgress`, and
61
- // `cancel` methods.
62
- _task: any;
63
-
64
- // constants
65
- get UNSENT() {
66
- return UNSENT;
67
- }
68
-
69
- get OPENED() {
70
- return OPENED;
71
- }
72
-
73
- get HEADERS_RECEIVED() {
74
- return HEADERS_RECEIVED;
75
- }
76
-
77
- get LOADING() {
78
- return LOADING;
79
- }
80
-
81
- get DONE() {
82
- return DONE;
83
- }
84
-
85
- static get UNSENT() {
86
- return UNSENT;
87
- }
88
-
89
- static get OPENED() {
90
- return OPENED;
91
- }
92
-
93
- static get HEADERS_RECEIVED() {
94
- return HEADERS_RECEIVED;
95
- }
96
-
97
- static get LOADING() {
98
- return LOADING;
99
- }
100
-
101
- static get DONE() {
102
- return DONE;
103
- }
104
-
105
- static setLog(level: number) {
106
- if (level === -1)
107
- log.disable();
108
- else
109
- log.level(level);
110
- }
111
-
112
- static addBinaryContentType(substr: string) {
113
- for (let i in XMLHttpRequest.binaryContentTypes) {
114
- if (new RegExp(substr, 'i').test(XMLHttpRequest.binaryContentTypes[i])) {
115
- return;
116
- }
117
- }
118
- XMLHttpRequest.binaryContentTypes.push(substr);
119
-
120
- }
121
-
122
- static removeBinaryContentType(val) {
123
- for (let i in XMLHttpRequest.binaryContentTypes) {
124
- if (new RegExp(substr, 'i').test(XMLHttpRequest.binaryContentTypes[i])) {
125
- XMLHttpRequest.binaryContentTypes.splice(i, 1);
126
- return;
127
- }
128
- }
129
- }
130
-
131
- constructor() {
132
- log.verbose('XMLHttpRequest constructor called');
133
- super();
134
- }
135
-
136
-
137
- /**
138
- * XMLHttpRequest.open, always async, user and password not supported. When
139
- * this method invoked, headers should becomes empty again.
140
- * @param {string} method Request method
141
- * @param {string} url Request URL
142
- * @param {true} async Always async
143
- * @param {any} user NOT SUPPORTED
144
- * @param {any} password NOT SUPPORTED
145
- */
146
- open(method: string, url: string, async: true, user: any, password: any) {
147
- log.verbose('XMLHttpRequest open ', method, url, async, user, password);
148
- this._method = method;
149
- this._url = url;
150
- this._headers = {};
151
- this._increment = URIUtil.isJSONStreamURI(this._url);
152
- this._url = this._url.replace(/^JSONStream\:\/\//, '');
153
- this._dispatchReadStateChange(XMLHttpRequest.OPENED);
154
- }
155
-
156
- /**
157
- * Invoke this function to send HTTP request, and set body.
158
- * @param {any} body Body in ReactNativeBlobUtil flavor
159
- */
160
- send(body) {
161
-
162
- this._body = body;
163
-
164
- if (this._readyState !== XMLHttpRequest.OPENED)
165
- throw 'InvalidStateError : XMLHttpRequest is not opened yet.';
166
- let promise = Promise.resolve();
167
- this._sendFlag = true;
168
- log.verbose('XMLHttpRequest send ', body);
169
- let {_method, _url, _headers} = this;
170
- log.verbose('sending request with args', _method, _url, _headers, body);
171
- log.verbose(typeof body, body instanceof FormData);
172
-
173
- if (body instanceof FormData) {
174
- log.debug('creating blob and setting header from FormData instance');
175
- body = new Blob(body);
176
- this._headers['Content-Type'] = `multipart/form-data; boundary=${body.multipartBoundary}`;
177
- }
178
-
179
- if (body instanceof Blob) {
180
- log.debug('sending blob body', body._blobCreated);
181
- promise = new Promise((resolve, reject) => {
182
- body.onCreated((blob) => {
183
- // when the blob is derived (not created by RN developer), the blob
184
- // will be released after XMLHttpRequest sent
185
- if (blob.isDerived) {
186
- this._cleanUp = () => {
187
- blob.close();
188
- };
189
- }
190
- log.debug('body created send request');
191
- body = URIUtil.wrap(blob.getReactNativeBlobUtilRef());
192
- resolve();
193
- });
194
- });
195
- }
196
- else if (typeof body === 'object') {
197
- body = JSON.stringify(body);
198
- promise = Promise.resolve();
199
- }
200
- else {
201
- body = body ? body.toString() : body;
202
- promise = Promise.resolve();
203
- }
204
-
205
- promise.then(() => {
206
- log.debug('send request invoke', body);
207
- for (let h in _headers) {
208
- _headers[h] = _headers[h].toString();
209
- }
210
-
211
- this._task = config({
212
- auto: true,
213
- timeout: this._timeout,
214
- increment: this._increment,
215
- binaryContentTypes: XMLHttpRequest.binaryContentTypes
216
- })
217
- .fetch(_method, _url, _headers, body);
218
- this._task
219
- .stateChange(this._headerReceived)
220
- .uploadProgress(this._uploadProgressEvent)
221
- .progress(this._progressEvent)
222
- .catch(this._onError)
223
- .then(this._onDone);
224
-
225
- });
226
- }
227
-
228
- overrideMimeType(mime: string) {
229
- log.verbose('XMLHttpRequest overrideMimeType', mime);
230
- this._headers['Content-Type'] = mime;
231
- }
232
-
233
- setRequestHeader(name, value) {
234
- log.verbose('XMLHttpRequest set header', name, value);
235
- if (this._readyState !== OPENED || this._sendFlag) {
236
- throw `InvalidStateError : Calling setRequestHeader in wrong state ${this._readyState}`;
237
- }
238
- // UNICODE SHOULD NOT PASS
239
- if (typeof name !== 'string' || /[^\u0000-\u00ff]/.test(name)) {
240
- throw 'TypeError : header field name should be a string';
241
- }
242
- //
243
- let invalidPatterns = [
244
- /[\(\)\>\<\@\,\:\\\/\[\]\?\=\}\{\s\ \u007f\;\t\0\v\r]/,
245
- /tt/
246
- ];
247
- for (let pattern of invalidPatterns) {
248
- if (pattern.test(name) || typeof name !== 'string') {
249
- throw `SyntaxError : Invalid header field name ${name}`;
250
- }
251
- }
252
- this._headers[name] = value;
253
- }
254
-
255
- abort() {
256
- log.verbose('XMLHttpRequest abort ');
257
- if (!this._task)
258
- return;
259
- this._task.cancel((err) => {
260
- let e = {
261
- timeStamp: Date.now(),
262
- };
263
- if (this.onabort)
264
- this.onabort();
265
- if (err) {
266
- e.detail = err;
267
- e.type = 'error';
268
- this.dispatchEvent('error', e);
269
- }
270
- else {
271
- e.type = 'abort';
272
- this.dispatchEvent('abort', e);
273
- }
274
- });
275
- }
276
-
277
- getResponseHeader(field: string): string | null {
278
- log.verbose('XMLHttpRequest get header', field, this._responseHeaders);
279
- if (!this._responseHeaders)
280
- return null;
281
- return this._responseHeaders[field] || this._responseHeaders[field.toLowerCase()] || null;
282
-
283
- }
284
-
285
- getAllResponseHeaders(): string | null {
286
- log.verbose('XMLHttpRequest get all headers', this._responseHeaders);
287
- if (!this._responseHeaders)
288
- return '';
289
- let result = '';
290
- let respHeaders = this.responseHeaders;
291
- for (let i in respHeaders) {
292
- result += `${i}: ${respHeaders[i]}${String.fromCharCode(0x0D, 0x0A)}`;
293
- }
294
- return result.substr(0, result.length - 2);
295
- }
296
-
297
- _headerReceived = (e) => {
298
- log.debug('header received ', this._task.taskId, e);
299
- this.responseURL = this._url;
300
- if (e.state === "2" && e.taskId === this._task.taskId) {
301
- this._responseHeaders = e.headers;
302
- this._statusText = e.status;
303
- this._status = Math.floor(e.status);
304
- this._dispatchReadStateChange(XMLHttpRequest.HEADERS_RECEIVED);
305
- }
306
- }
307
-
308
- _uploadProgressEvent = (send: number, total: number) => {
309
- if (!this._uploadStarted) {
310
- this.upload.dispatchEvent('loadstart');
311
- this._uploadStarted = true;
312
- }
313
- if (send >= total)
314
- this.upload.dispatchEvent('load');
315
- this.upload.dispatchEvent('progress', new ProgressEvent(true, send, total));
316
- }
317
-
318
- _progressEvent = (send: number, total: number, chunk: string) => {
319
- log.verbose(this.readyState);
320
- if (this._readyState === XMLHttpRequest.HEADERS_RECEIVED)
321
- this._dispatchReadStateChange(XMLHttpRequest.LOADING);
322
- let lengthComputable = false;
323
- if (total && total >= 0)
324
- lengthComputable = true;
325
- let e = new ProgressEvent(lengthComputable, send, total);
326
-
327
- if (this._increment) {
328
- this._responseText += chunk;
329
- }
330
- this.dispatchEvent('progress', e);
331
- }
332
-
333
- _onError = (err) => {
334
- let statusCode = Math.floor(this.status);
335
- if (statusCode >= 100 && statusCode !== 408) {
336
- return;
337
- }
338
- log.debug('XMLHttpRequest error', err);
339
- this._statusText = err;
340
- this._status = String(err).match(/\d+/);
341
- this._status = this._status ? Math.floor(this.status) : 404;
342
- this._dispatchReadStateChange(XMLHttpRequest.DONE);
343
- if (err && String(err.message).match(/(timed\sout|timedout)/) || this._status == 408) {
344
- this.dispatchEvent('timeout');
345
- }
346
- this.dispatchEvent('loadend');
347
- this.dispatchEvent('error', {
348
- type: 'error',
349
- detail: err
350
- });
351
- this.clearEventListeners();
352
- }
353
-
354
- _onDone = (resp) => {
355
- log.debug('XMLHttpRequest done', this._url, resp, this);
356
- this._statusText = this._status;
357
- let responseDataReady = () => {
358
- log.debug('request done state = 4');
359
- this.dispatchEvent('load');
360
- this.dispatchEvent('loadend');
361
- this._dispatchReadStateChange(XMLHttpRequest.DONE);
362
- this.clearEventListeners();
363
- };
364
- if (resp) {
365
- let info = resp.respInfo || {};
366
- log.debug(this._url, info, info.respType);
367
- switch (this._responseType) {
368
- case 'blob' :
369
- resp.blob().then((b) => {
370
- this._responseText = resp.text();
371
- this._response = b;
372
- responseDataReady();
373
- });
374
- break;
375
- case 'arraybuffer':
376
- // TODO : to array buffer
377
- break;
378
- case 'json':
379
- this._response = resp.json();
380
- this._responseText = resp.text();
381
- break;
382
- default :
383
- this._responseText = resp.text();
384
- this._response = this.responseText;
385
- responseDataReady();
386
- break;
387
- }
388
- }
389
-
390
- }
391
-
392
- _dispatchReadStateChange(state) {
393
- this._readyState = state;
394
- if (typeof this._onreadystatechange === 'function')
395
- this._onreadystatechange();
396
- }
397
-
398
- set onreadystatechange(fn: () => void) {
399
- log.verbose('XMLHttpRequest set onreadystatechange', fn);
400
- this._onreadystatechange = fn;
401
- }
402
-
403
- get onreadystatechange() {
404
- return this._onreadystatechange;
405
- }
406
-
407
- get readyState() {
408
- log.verbose('get readyState', this._readyState);
409
- return this._readyState;
410
- }
411
-
412
- get status() {
413
- log.verbose('get status', this._status);
414
- return this._status;
415
- }
416
-
417
- get statusText() {
418
- log.verbose('get statusText', this._statusText);
419
- return this._statusText;
420
- }
421
-
422
- get response() {
423
- log.verbose('get response', this._response);
424
- return this._response;
425
- }
426
-
427
- get responseText() {
428
- log.verbose('get responseText', this._responseText);
429
- return this._responseText;
430
- }
431
-
432
- get responseURL() {
433
- log.verbose('get responseURL', this._responseURL);
434
- return this._responseURL;
435
- }
436
-
437
- get responseHeaders() {
438
- log.verbose('get responseHeaders', this._responseHeaders);
439
- return this._responseHeaders;
440
- }
441
-
442
- set timeout(val) {
443
- this._timeout = val * 1000;
444
- log.verbose('set timeout', this._timeout);
445
- }
446
-
447
- get timeout() {
448
- log.verbose('get timeout', this._timeout);
449
- return this._timeout;
450
- }
451
-
452
- set responseType(val) {
453
- log.verbose('set response type', this._responseType);
454
- this._responseType = val;
455
- }
456
-
457
- get responseType() {
458
- log.verbose('get response type', this._responseType);
459
- return this._responseType;
460
- }
461
-
462
- static get isRNFBPolyfill() {
463
- return true;
464
- }
465
-
466
- }
1
+ // Copyright 2016 wkh237@github. All rights reserved.
2
+ // Use of this source code is governed by a MIT-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import XMLHttpRequestEventTarget from './XMLHttpRequestEventTarget.js';
6
+ import Log from '../utils/log.js';
7
+ import Blob from './Blob.js';
8
+ import ProgressEvent from './ProgressEvent.js';
9
+ import URIUtil from "../utils/uri";
10
+ import {config} from "../fetch";
11
+
12
+ const log = new Log('XMLHttpRequest');
13
+
14
+
15
+ log.disable();
16
+ // log.level(3)
17
+
18
+ const UNSENT = 0;
19
+ const OPENED = 1;
20
+ const HEADERS_RECEIVED = 2;
21
+ const LOADING = 3;
22
+ const DONE = 4;
23
+
24
+ export default class XMLHttpRequest extends XMLHttpRequestEventTarget {
25
+
26
+ _onreadystatechange: () => void;
27
+
28
+ upload: XMLHttpRequestEventTarget = new XMLHttpRequestEventTarget();
29
+ static binaryContentTypes: Array<string> = [
30
+ 'image/', 'video/', 'audio/'
31
+ ];
32
+
33
+ // readonly
34
+ _readyState: number = UNSENT;
35
+ _uriType: 'net' | 'file' = 'net';
36
+ _response: any = '';
37
+ _responseText: any = '';
38
+ _responseHeaders: any = {};
39
+ _responseType: '' | 'arraybuffer' | 'blob' | 'json' | 'text' = '';
40
+ // TODO : not suppoted ATM
41
+ _responseURL: null = '';
42
+ _responseXML: null = '';
43
+ _status: number = 0;
44
+ _statusText: string = '';
45
+ _timeout: number = 60000;
46
+ _sendFlag: boolean = false;
47
+ _uploadStarted: boolean = false;
48
+ _increment: boolean = false;
49
+
50
+ // ReactNativeBlobUtil compatible data structure
51
+ _config: ReactNativeBlobUtilConfig = {};
52
+ _url: any;
53
+ _method: string;
54
+ _headers: any = {
55
+ 'Content-Type': 'text/plain'
56
+ };
57
+ _cleanUp: () => void = null;
58
+ _body: any;
59
+
60
+ // ReactNativeBlobUtil promise object, which has `progress`, `uploadProgress`, and
61
+ // `cancel` methods.
62
+ _task: any;
63
+
64
+ // constants
65
+ get UNSENT() {
66
+ return UNSENT;
67
+ }
68
+
69
+ get OPENED() {
70
+ return OPENED;
71
+ }
72
+
73
+ get HEADERS_RECEIVED() {
74
+ return HEADERS_RECEIVED;
75
+ }
76
+
77
+ get LOADING() {
78
+ return LOADING;
79
+ }
80
+
81
+ get DONE() {
82
+ return DONE;
83
+ }
84
+
85
+ static get UNSENT() {
86
+ return UNSENT;
87
+ }
88
+
89
+ static get OPENED() {
90
+ return OPENED;
91
+ }
92
+
93
+ static get HEADERS_RECEIVED() {
94
+ return HEADERS_RECEIVED;
95
+ }
96
+
97
+ static get LOADING() {
98
+ return LOADING;
99
+ }
100
+
101
+ static get DONE() {
102
+ return DONE;
103
+ }
104
+
105
+ static setLog(level: number) {
106
+ if (level === -1)
107
+ log.disable();
108
+ else
109
+ log.level(level);
110
+ }
111
+
112
+ static addBinaryContentType(substr: string) {
113
+ for (let i in XMLHttpRequest.binaryContentTypes) {
114
+ if (new RegExp(substr, 'i').test(XMLHttpRequest.binaryContentTypes[i])) {
115
+ return;
116
+ }
117
+ }
118
+ XMLHttpRequest.binaryContentTypes.push(substr);
119
+
120
+ }
121
+
122
+ static removeBinaryContentType(val) {
123
+ for (let i in XMLHttpRequest.binaryContentTypes) {
124
+ if (new RegExp(substr, 'i').test(XMLHttpRequest.binaryContentTypes[i])) {
125
+ XMLHttpRequest.binaryContentTypes.splice(i, 1);
126
+ return;
127
+ }
128
+ }
129
+ }
130
+
131
+ constructor() {
132
+ log.verbose('XMLHttpRequest constructor called');
133
+ super();
134
+ }
135
+
136
+
137
+ /**
138
+ * XMLHttpRequest.open, always async, user and password not supported. When
139
+ * this method invoked, headers should becomes empty again.
140
+ * @param {string} method Request method
141
+ * @param {string} url Request URL
142
+ * @param {true} async Always async
143
+ * @param {any} user NOT SUPPORTED
144
+ * @param {any} password NOT SUPPORTED
145
+ */
146
+ open(method: string, url: string, async: true, user: any, password: any) {
147
+ log.verbose('XMLHttpRequest open ', method, url, async, user, password);
148
+ this._method = method;
149
+ this._url = url;
150
+ this._headers = {};
151
+ this._increment = URIUtil.isJSONStreamURI(this._url);
152
+ this._url = this._url.replace(/^JSONStream\:\/\//, '');
153
+ this._dispatchReadStateChange(XMLHttpRequest.OPENED);
154
+ }
155
+
156
+ /**
157
+ * Invoke this function to send HTTP request, and set body.
158
+ * @param {any} body Body in ReactNativeBlobUtil flavor
159
+ */
160
+ send(body) {
161
+
162
+ this._body = body;
163
+
164
+ if (this._readyState !== XMLHttpRequest.OPENED)
165
+ throw 'InvalidStateError : XMLHttpRequest is not opened yet.';
166
+ let promise = Promise.resolve();
167
+ this._sendFlag = true;
168
+ log.verbose('XMLHttpRequest send ', body);
169
+ let {_method, _url, _headers} = this;
170
+ log.verbose('sending request with args', _method, _url, _headers, body);
171
+ log.verbose(typeof body, body instanceof FormData);
172
+
173
+ if (body instanceof FormData) {
174
+ log.debug('creating blob and setting header from FormData instance');
175
+ body = new Blob(body);
176
+ this._headers['Content-Type'] = `multipart/form-data; boundary=${body.multipartBoundary}`;
177
+ }
178
+
179
+ if (body instanceof Blob) {
180
+ log.debug('sending blob body', body._blobCreated);
181
+ promise = new Promise((resolve, reject) => {
182
+ body.onCreated((blob) => {
183
+ // when the blob is derived (not created by RN developer), the blob
184
+ // will be released after XMLHttpRequest sent
185
+ if (blob.isDerived) {
186
+ this._cleanUp = () => {
187
+ blob.close();
188
+ };
189
+ }
190
+ log.debug('body created send request');
191
+ body = URIUtil.wrap(blob.getReactNativeBlobUtilRef());
192
+ resolve();
193
+ });
194
+ });
195
+ }
196
+ else if (typeof body === 'object') {
197
+ body = JSON.stringify(body);
198
+ promise = Promise.resolve();
199
+ }
200
+ else {
201
+ body = body ? body.toString() : body;
202
+ promise = Promise.resolve();
203
+ }
204
+
205
+ promise.then(() => {
206
+ log.debug('send request invoke', body);
207
+ for (let h in _headers) {
208
+ _headers[h] = _headers[h].toString();
209
+ }
210
+
211
+ this._task = config({
212
+ auto: true,
213
+ timeout: this._timeout,
214
+ increment: this._increment,
215
+ binaryContentTypes: XMLHttpRequest.binaryContentTypes
216
+ })
217
+ .fetch(_method, _url, _headers, body);
218
+ this._task
219
+ .stateChange(this._headerReceived)
220
+ .uploadProgress(this._uploadProgressEvent)
221
+ .progress(this._progressEvent)
222
+ .catch(this._onError)
223
+ .then(this._onDone);
224
+
225
+ });
226
+ }
227
+
228
+ overrideMimeType(mime: string) {
229
+ log.verbose('XMLHttpRequest overrideMimeType', mime);
230
+ this._headers['Content-Type'] = mime;
231
+ }
232
+
233
+ setRequestHeader(name, value) {
234
+ log.verbose('XMLHttpRequest set header', name, value);
235
+ if (this._readyState !== OPENED || this._sendFlag) {
236
+ throw `InvalidStateError : Calling setRequestHeader in wrong state ${this._readyState}`;
237
+ }
238
+ // UNICODE SHOULD NOT PASS
239
+ if (typeof name !== 'string' || /[^\u0000-\u00ff]/.test(name)) {
240
+ throw 'TypeError : header field name should be a string';
241
+ }
242
+ //
243
+ let invalidPatterns = [
244
+ /[\(\)\>\<\@\,\:\\\/\[\]\?\=\}\{\s\ \u007f\;\t\0\v\r]/,
245
+ /tt/
246
+ ];
247
+ for (let pattern of invalidPatterns) {
248
+ if (pattern.test(name) || typeof name !== 'string') {
249
+ throw `SyntaxError : Invalid header field name ${name}`;
250
+ }
251
+ }
252
+ this._headers[name] = value;
253
+ }
254
+
255
+ abort() {
256
+ log.verbose('XMLHttpRequest abort ');
257
+ if (!this._task)
258
+ return;
259
+ this._task.cancel((err) => {
260
+ let e = {
261
+ timeStamp: Date.now(),
262
+ };
263
+ if (this.onabort)
264
+ this.onabort();
265
+ if (err) {
266
+ e.detail = err;
267
+ e.type = 'error';
268
+ this.dispatchEvent('error', e);
269
+ }
270
+ else {
271
+ e.type = 'abort';
272
+ this.dispatchEvent('abort', e);
273
+ }
274
+ });
275
+ }
276
+
277
+ getResponseHeader(field: string): string | null {
278
+ log.verbose('XMLHttpRequest get header', field, this._responseHeaders);
279
+ if (!this._responseHeaders)
280
+ return null;
281
+ return this._responseHeaders[field] || this._responseHeaders[field.toLowerCase()] || null;
282
+
283
+ }
284
+
285
+ getAllResponseHeaders(): string | null {
286
+ log.verbose('XMLHttpRequest get all headers', this._responseHeaders);
287
+ if (!this._responseHeaders)
288
+ return '';
289
+ let result = '';
290
+ let respHeaders = this.responseHeaders;
291
+ for (let i in respHeaders) {
292
+ result += `${i}: ${respHeaders[i]}${String.fromCharCode(0x0D, 0x0A)}`;
293
+ }
294
+ return result.substr(0, result.length - 2);
295
+ }
296
+
297
+ _headerReceived = (e) => {
298
+ log.debug('header received ', this._task.taskId, e);
299
+ this.responseURL = this._url;
300
+ if (e.state === "2" && e.taskId === this._task.taskId) {
301
+ this._responseHeaders = e.headers;
302
+ this._statusText = e.status;
303
+ this._status = Math.floor(e.status);
304
+ this._dispatchReadStateChange(XMLHttpRequest.HEADERS_RECEIVED);
305
+ }
306
+ }
307
+
308
+ _uploadProgressEvent = (send: number, total: number) => {
309
+ if (!this._uploadStarted) {
310
+ this.upload.dispatchEvent('loadstart');
311
+ this._uploadStarted = true;
312
+ }
313
+ if (send >= total)
314
+ this.upload.dispatchEvent('load');
315
+ this.upload.dispatchEvent('progress', new ProgressEvent(true, send, total));
316
+ }
317
+
318
+ _progressEvent = (send: number, total: number, chunk: string) => {
319
+ log.verbose(this.readyState);
320
+ if (this._readyState === XMLHttpRequest.HEADERS_RECEIVED)
321
+ this._dispatchReadStateChange(XMLHttpRequest.LOADING);
322
+ let lengthComputable = false;
323
+ if (total && total >= 0)
324
+ lengthComputable = true;
325
+ let e = new ProgressEvent(lengthComputable, send, total);
326
+
327
+ if (this._increment) {
328
+ this._responseText += chunk;
329
+ }
330
+ this.dispatchEvent('progress', e);
331
+ }
332
+
333
+ _onError = (err) => {
334
+ let statusCode = Math.floor(this.status);
335
+ if (statusCode >= 100 && statusCode !== 408) {
336
+ return;
337
+ }
338
+ log.debug('XMLHttpRequest error', err);
339
+ this._statusText = err;
340
+ this._status = String(err).match(/\d+/);
341
+ this._status = this._status ? Math.floor(this.status) : 404;
342
+ this._dispatchReadStateChange(XMLHttpRequest.DONE);
343
+ if (err && String(err.message).match(/(timed\sout|timedout)/) || this._status == 408) {
344
+ this.dispatchEvent('timeout');
345
+ }
346
+ this.dispatchEvent('loadend');
347
+ this.dispatchEvent('error', {
348
+ type: 'error',
349
+ detail: err
350
+ });
351
+ this.clearEventListeners();
352
+ }
353
+
354
+ _onDone = (resp) => {
355
+ log.debug('XMLHttpRequest done', this._url, resp, this);
356
+ this._statusText = this._status;
357
+ let responseDataReady = () => {
358
+ log.debug('request done state = 4');
359
+ this.dispatchEvent('load');
360
+ this.dispatchEvent('loadend');
361
+ this._dispatchReadStateChange(XMLHttpRequest.DONE);
362
+ this.clearEventListeners();
363
+ };
364
+ if (resp) {
365
+ let info = resp.respInfo || {};
366
+ log.debug(this._url, info, info.respType);
367
+ switch (this._responseType) {
368
+ case 'blob' :
369
+ resp.blob().then((b) => {
370
+ this._responseText = resp.text();
371
+ this._response = b;
372
+ responseDataReady();
373
+ });
374
+ break;
375
+ case 'arraybuffer':
376
+ // TODO : to array buffer
377
+ break;
378
+ case 'json':
379
+ this._response = resp.json();
380
+ this._responseText = resp.text();
381
+ break;
382
+ default :
383
+ this._responseText = resp.text();
384
+ this._response = this.responseText;
385
+ responseDataReady();
386
+ break;
387
+ }
388
+ }
389
+
390
+ }
391
+
392
+ _dispatchReadStateChange(state) {
393
+ this._readyState = state;
394
+ if (typeof this._onreadystatechange === 'function')
395
+ this._onreadystatechange();
396
+ }
397
+
398
+ set onreadystatechange(fn: () => void) {
399
+ log.verbose('XMLHttpRequest set onreadystatechange', fn);
400
+ this._onreadystatechange = fn;
401
+ }
402
+
403
+ get onreadystatechange() {
404
+ return this._onreadystatechange;
405
+ }
406
+
407
+ get readyState() {
408
+ log.verbose('get readyState', this._readyState);
409
+ return this._readyState;
410
+ }
411
+
412
+ get status() {
413
+ log.verbose('get status', this._status);
414
+ return this._status;
415
+ }
416
+
417
+ get statusText() {
418
+ log.verbose('get statusText', this._statusText);
419
+ return this._statusText;
420
+ }
421
+
422
+ get response() {
423
+ log.verbose('get response', this._response);
424
+ return this._response;
425
+ }
426
+
427
+ get responseText() {
428
+ log.verbose('get responseText', this._responseText);
429
+ return this._responseText;
430
+ }
431
+
432
+ get responseURL() {
433
+ log.verbose('get responseURL', this._responseURL);
434
+ return this._responseURL;
435
+ }
436
+
437
+ get responseHeaders() {
438
+ log.verbose('get responseHeaders', this._responseHeaders);
439
+ return this._responseHeaders;
440
+ }
441
+
442
+ set timeout(val) {
443
+ this._timeout = val * 1000;
444
+ log.verbose('set timeout', this._timeout);
445
+ }
446
+
447
+ get timeout() {
448
+ log.verbose('get timeout', this._timeout);
449
+ return this._timeout;
450
+ }
451
+
452
+ set responseType(val) {
453
+ log.verbose('set response type', this._responseType);
454
+ this._responseType = val;
455
+ }
456
+
457
+ get responseType() {
458
+ log.verbose('get response type', this._responseType);
459
+ return this._responseType;
460
+ }
461
+
462
+ static get isRNFBPolyfill() {
463
+ return true;
464
+ }
465
+
466
+ }