@tarojs/plugin-http 3.8.0-canary.0 → 3.8.0-canary.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/LICENSE +14 -0
- package/dist/runtime.d.ts +4 -1
- package/dist/runtime.js +51 -16
- package/package.json +7 -7
- package/src/__tests__/cookie.spec.js +0 -1
- package/src/__tests__/dom.spec.js +1 -3
- package/src/__tests__/xhr.spec.ts +101 -0
- package/src/runtime/Cookie.ts +1 -1
- package/src/runtime/XMLHttpRequest.ts +41 -15
- package/src/runtime/index.ts +2 -3
package/LICENSE
CHANGED
|
@@ -158,3 +158,17 @@ MIT (stencil-vue2-output-target):
|
|
|
158
158
|
The following files embed [stencil-vue2-output-target](https://github.com/diondree/stencil-vue2-output-target) MIT:
|
|
159
159
|
`/packages/taro-components-library-vue2/src/vue-component-lib/utils.ts`
|
|
160
160
|
See `/LICENSE` for details of the license.
|
|
161
|
+
|
|
162
|
+
==================
|
|
163
|
+
|
|
164
|
+
MIT (weui):
|
|
165
|
+
The following files embed [stencil-vue2-output-target](https://github.com/Tencent/weui) MIT:
|
|
166
|
+
`/packages/taro-components/src/components/*.scss`
|
|
167
|
+
See `/LICENSE.txt` for details of the license.
|
|
168
|
+
|
|
169
|
+
==================
|
|
170
|
+
|
|
171
|
+
Apache-2.0 (intersection-observer):
|
|
172
|
+
The following files embed [intersection-observer](https://github.com/GoogleChromeLabs/intersection-observer) Apache-2.0:
|
|
173
|
+
`/packages/taro-api/src/polyfill/intersection-observer.ts`
|
|
174
|
+
See `/LICENSE.txt` for details of the license.
|
package/dist/runtime.d.ts
CHANGED
|
@@ -58,7 +58,10 @@ declare class XMLHttpRequest extends Events {
|
|
|
58
58
|
// 欺骗一些库让其认为是原生的xhr
|
|
59
59
|
static toString(): string;
|
|
60
60
|
toString(): string;
|
|
61
|
-
//
|
|
61
|
+
// 事件正常流转: loadstart => progress(可能多次) => load => loadend
|
|
62
|
+
// error 流转: loadstart => error => loadend
|
|
63
|
+
// abort 流转: loadstart => abort => loadend
|
|
64
|
+
// web在线测试: https://developer.mozilla.org/zh-CN/play
|
|
62
65
|
/** 当 request 被停止时触发,例如当程序调用 XMLHttpRequest.abort() 时 */
|
|
63
66
|
onabort: ((e: XMLHttpRequestEvent) => void) | null;
|
|
64
67
|
/** 当 request 遭遇错误时触发 */
|
package/dist/runtime.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parseUrl, Events, createEvent, window, document } from '@tarojs/runtime';
|
|
2
2
|
export { document } from '@tarojs/runtime';
|
|
3
|
-
import { isString, isFunction, isWebPlatform } from '@tarojs/shared';
|
|
4
3
|
import { setStorage, getStorageSync, request } from '@tarojs/taro';
|
|
4
|
+
import { isString, isFunction } from '@tarojs/shared';
|
|
5
5
|
|
|
6
6
|
/******************************************************************************
|
|
7
7
|
Copyright (c) Microsoft Corporation.
|
|
@@ -17,7 +17,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
17
17
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
18
18
|
PERFORMANCE OF THIS SOFTWARE.
|
|
19
19
|
***************************************************************************** */
|
|
20
|
-
/* global Reflect, Promise */
|
|
20
|
+
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
function __classPrivateFieldGet(receiver, state, kind, f) {
|
|
@@ -31,7 +31,12 @@ function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
|
|
31
31
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
32
32
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
33
33
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
34
|
-
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
37
|
+
var e = new Error(message);
|
|
38
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
39
|
+
};
|
|
35
40
|
|
|
36
41
|
var _Cookie_map;
|
|
37
42
|
const STORAGE_KEY = 'PAGE_COOKIE';
|
|
@@ -357,20 +362,20 @@ function createXMLHttpRequestEvent(event, target, loaded) {
|
|
|
357
362
|
const e = createEvent(event);
|
|
358
363
|
try {
|
|
359
364
|
Object.defineProperties(e, {
|
|
360
|
-
|
|
365
|
+
currentTarget: {
|
|
361
366
|
enumerable: true,
|
|
362
367
|
value: target
|
|
363
368
|
},
|
|
364
|
-
|
|
369
|
+
target: {
|
|
365
370
|
enumerable: true,
|
|
366
371
|
value: target
|
|
367
372
|
},
|
|
368
|
-
|
|
373
|
+
loaded: {
|
|
369
374
|
enumerable: true,
|
|
370
375
|
value: loaded || 0
|
|
371
376
|
},
|
|
372
377
|
// 读 Content-Range 字段,目前来说作用不大,先和 loaded 保持一致
|
|
373
|
-
|
|
378
|
+
total: {
|
|
374
379
|
enumerable: true,
|
|
375
380
|
value: loaded || 0
|
|
376
381
|
}
|
|
@@ -406,7 +411,10 @@ class XMLHttpRequest extends Events {
|
|
|
406
411
|
_XMLHttpRequest_timeout.set(this, void 0);
|
|
407
412
|
_XMLHttpRequest_withCredentials.set(this, void 0);
|
|
408
413
|
_XMLHttpRequest_requestTask.set(this, void 0);
|
|
409
|
-
//
|
|
414
|
+
// 事件正常流转: loadstart => progress(可能多次) => load => loadend
|
|
415
|
+
// error 流转: loadstart => error => loadend
|
|
416
|
+
// abort 流转: loadstart => abort => loadend
|
|
417
|
+
// web在线测试: https://developer.mozilla.org/zh-CN/play
|
|
410
418
|
/** 当 request 被停止时触发,例如当程序调用 XMLHttpRequest.abort() 时 */
|
|
411
419
|
this.onabort = null;
|
|
412
420
|
/** 当 request 遭遇错误时触发 */
|
|
@@ -502,15 +510,17 @@ class XMLHttpRequest extends Events {
|
|
|
502
510
|
}
|
|
503
511
|
}
|
|
504
512
|
getAllResponseHeaders() {
|
|
505
|
-
if (__classPrivateFieldGet(this, _XMLHttpRequest_readyState, "f") === XMLHttpRequest.UNSENT || __classPrivateFieldGet(this, _XMLHttpRequest_readyState, "f") === XMLHttpRequest.OPENED || !__classPrivateFieldGet(this, _XMLHttpRequest_resHeader, "f"))
|
|
513
|
+
if (__classPrivateFieldGet(this, _XMLHttpRequest_readyState, "f") === XMLHttpRequest.UNSENT || __classPrivateFieldGet(this, _XMLHttpRequest_readyState, "f") === XMLHttpRequest.OPENED || !__classPrivateFieldGet(this, _XMLHttpRequest_resHeader, "f")) {
|
|
506
514
|
return '';
|
|
515
|
+
}
|
|
507
516
|
return Object.keys(__classPrivateFieldGet(this, _XMLHttpRequest_resHeader, "f"))
|
|
508
517
|
.map((key) => `${key}: ${__classPrivateFieldGet(this, _XMLHttpRequest_resHeader, "f")[key]}`)
|
|
509
518
|
.join('\r\n');
|
|
510
519
|
}
|
|
511
520
|
getResponseHeader(name) {
|
|
512
|
-
if (__classPrivateFieldGet(this, _XMLHttpRequest_readyState, "f") === XMLHttpRequest.UNSENT || __classPrivateFieldGet(this, _XMLHttpRequest_readyState, "f") === XMLHttpRequest.OPENED || !__classPrivateFieldGet(this, _XMLHttpRequest_resHeader, "f"))
|
|
521
|
+
if (__classPrivateFieldGet(this, _XMLHttpRequest_readyState, "f") === XMLHttpRequest.UNSENT || __classPrivateFieldGet(this, _XMLHttpRequest_readyState, "f") === XMLHttpRequest.OPENED || !__classPrivateFieldGet(this, _XMLHttpRequest_resHeader, "f")) {
|
|
513
522
|
return null;
|
|
523
|
+
}
|
|
514
524
|
// 处理大小写不敏感
|
|
515
525
|
const key = Object.keys(__classPrivateFieldGet(this, _XMLHttpRequest_resHeader, "f")).find((item) => item.toLowerCase() === name.toLowerCase());
|
|
516
526
|
const value = key ? __classPrivateFieldGet(this, _XMLHttpRequest_resHeader, "f")[key] : null;
|
|
@@ -577,6 +587,7 @@ _XMLHttpRequest_method = new WeakMap(), _XMLHttpRequest_url = new WeakMap(), _XM
|
|
|
577
587
|
// 头信息
|
|
578
588
|
const header = Object.assign({}, __classPrivateFieldGet(this, _XMLHttpRequest_header, "f"));
|
|
579
589
|
// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies
|
|
590
|
+
// @ts-ignore
|
|
580
591
|
header.cookie = window.document.$$cookie;
|
|
581
592
|
if (!this.withCredentials) {
|
|
582
593
|
// 不同源,要求 withCredentials 为 true 才携带 cookie
|
|
@@ -606,7 +617,7 @@ _XMLHttpRequest_method = new WeakMap(), _XMLHttpRequest_url = new WeakMap(), _XM
|
|
|
606
617
|
__classPrivateFieldGet(this, _XMLHttpRequest_instances, "m", _XMLHttpRequest_callReadyStateChange).call(this, XMLHttpRequest.HEADERS_RECEIVED);
|
|
607
618
|
if (ENABLE_COOKIE) {
|
|
608
619
|
// 处理 set-cookie
|
|
609
|
-
const setCookieStr =
|
|
620
|
+
const setCookieStr = this.getResponseHeader('set-cookie');
|
|
610
621
|
if (setCookieStr && typeof setCookieStr === 'string') {
|
|
611
622
|
let start = 0;
|
|
612
623
|
let startSplit = 0;
|
|
@@ -634,17 +645,40 @@ _XMLHttpRequest_method = new WeakMap(), _XMLHttpRequest_url = new WeakMap(), _XM
|
|
|
634
645
|
// 处理返回数据
|
|
635
646
|
if (data) {
|
|
636
647
|
__classPrivateFieldGet(this, _XMLHttpRequest_instances, "m", _XMLHttpRequest_callReadyStateChange).call(this, XMLHttpRequest.LOADING);
|
|
637
|
-
const
|
|
648
|
+
const contentLength = Number(this.getResponseHeader('content-length') || 0);
|
|
649
|
+
const loadstartEvent = createXMLHttpRequestEvent('loadstart', this, contentLength);
|
|
638
650
|
this.trigger('loadstart', loadstartEvent);
|
|
639
651
|
isFunction(this.onloadstart) && this.onloadstart(loadstartEvent);
|
|
640
652
|
__classPrivateFieldSet(this, _XMLHttpRequest_response, data, "f");
|
|
641
|
-
const loadEvent = createXMLHttpRequestEvent('load', this,
|
|
653
|
+
const loadEvent = createXMLHttpRequestEvent('load', this, contentLength);
|
|
642
654
|
this.trigger('load', loadEvent);
|
|
643
655
|
isFunction(this.onload) && this.onload(loadEvent);
|
|
644
656
|
}
|
|
645
657
|
}, _XMLHttpRequest_requestFail = function _XMLHttpRequest_requestFail(err) {
|
|
658
|
+
// 微信小程序,无论接口返回200还是其他,响应无论是否有错误,都会进入 success 回调;只有类似超时这种请求错误才会进入 fail 回调
|
|
659
|
+
//
|
|
660
|
+
/**
|
|
661
|
+
* 阿里系小程序,接口返回非200状态码,会进入 fail 回调, 此时 err 对象结构如下(当错误码为 14 或 19 时,会多返回 status、data、headers。可通过这些字段获取服务端相关错误信息):
|
|
662
|
+
{
|
|
663
|
+
data: "{\"code\": 401,\"msg\":\"登录过期,请重新登录\"}"
|
|
664
|
+
error: 19
|
|
665
|
+
errorMessage: "http status error"
|
|
666
|
+
headers: {date: 'Mon, 14 Aug 2023 08:54:58 GMT', content-type: 'application/json;charset=UTF-8', content-length: '52', connection: 'close', access-control-allow-credentials: 'true', …}
|
|
667
|
+
originalData: "{\"code\": 401,\"msg\":\"登录过期,请重新登录\"}"
|
|
668
|
+
status: 401
|
|
669
|
+
}
|
|
670
|
+
*/
|
|
671
|
+
// 统一行为,能正常响应的,都算 success.
|
|
672
|
+
if (err.status) {
|
|
673
|
+
__classPrivateFieldGet(this, _XMLHttpRequest_instances, "m", _XMLHttpRequest_requestSuccess).call(this, {
|
|
674
|
+
data: err,
|
|
675
|
+
statusCode: err.status,
|
|
676
|
+
header: err.headers
|
|
677
|
+
});
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
646
680
|
__classPrivateFieldSet(this, _XMLHttpRequest_status, 0, "f");
|
|
647
|
-
__classPrivateFieldSet(this, _XMLHttpRequest_statusText, err.errMsg, "f");
|
|
681
|
+
__classPrivateFieldSet(this, _XMLHttpRequest_statusText, err.errMsg || err.errorMessage, "f");
|
|
648
682
|
const errorEvent = createXMLHttpRequestEvent('error', this, 0);
|
|
649
683
|
this.trigger('error', errorEvent);
|
|
650
684
|
isFunction(this.onerror) && this.onerror(errorEvent);
|
|
@@ -652,7 +686,8 @@ _XMLHttpRequest_method = new WeakMap(), _XMLHttpRequest_url = new WeakMap(), _XM
|
|
|
652
686
|
__classPrivateFieldSet(this, _XMLHttpRequest_requestTask, null, "f");
|
|
653
687
|
__classPrivateFieldGet(this, _XMLHttpRequest_instances, "m", _XMLHttpRequest_callReadyStateChange).call(this, XMLHttpRequest.DONE);
|
|
654
688
|
if (__classPrivateFieldGet(this, _XMLHttpRequest_status, "f")) {
|
|
655
|
-
const
|
|
689
|
+
const contentLength = Number(this.getResponseHeader('content-length') || 0);
|
|
690
|
+
const loadendEvent = createXMLHttpRequestEvent('loadend', this, contentLength);
|
|
656
691
|
this.trigger('loadend', loadendEvent);
|
|
657
692
|
isFunction(this.onloadend) && this.onloadend(loadendEvent);
|
|
658
693
|
}
|
|
@@ -663,7 +698,7 @@ XMLHttpRequest.HEADERS_RECEIVED = 2;
|
|
|
663
698
|
XMLHttpRequest.LOADING = 3;
|
|
664
699
|
XMLHttpRequest.DONE = 4;
|
|
665
700
|
|
|
666
|
-
if (
|
|
701
|
+
if (process.env.TARO_PLATFORM !== 'web') {
|
|
667
702
|
if (ENABLE_COOKIE) {
|
|
668
703
|
const _cookie = createCookieInstance();
|
|
669
704
|
Object.defineProperties(document, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tarojs/plugin-http",
|
|
3
|
-
"version": "3.8.0-canary.
|
|
3
|
+
"version": "3.8.0-canary.1",
|
|
4
4
|
"description": "Taro 小程序端支持使用 web 请求 的插件",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -23,12 +23,12 @@
|
|
|
23
23
|
},
|
|
24
24
|
"homepage": "https://github.com/NervJS/taro#readme",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@tarojs/runtime": "3.8.0-canary.
|
|
27
|
-
"@tarojs/
|
|
28
|
-
"@tarojs/
|
|
26
|
+
"@tarojs/runtime": "3.8.0-canary.1",
|
|
27
|
+
"@tarojs/shared": "3.8.0-canary.1",
|
|
28
|
+
"@tarojs/service": "3.8.0-canary.1"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@rollup/plugin-json": "^
|
|
31
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
32
32
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
33
33
|
"jest": "^29.3.1",
|
|
34
34
|
"jest-cli": "^29.3.1",
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
"rollup-plugin-node-externals": "^5.0.0",
|
|
38
38
|
"rollup-plugin-ts": "^3.0.2",
|
|
39
39
|
"ts-jest": "^29.0.5",
|
|
40
|
-
"tslib": "^2.
|
|
40
|
+
"tslib": "^2.6.2",
|
|
41
41
|
"typescript": "^4.7.4"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"dev": "rollup -c -w --bundleConfigAsCjs",
|
|
45
45
|
"build": "rollup -c --bundleConfigAsCjs",
|
|
46
46
|
"test": "jest",
|
|
47
|
-
"test:ci": "jest --ci -i --coverage
|
|
47
|
+
"test:ci": "jest --ci -i --coverage --silent"
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -3,9 +3,8 @@ describe('DOM', () => {
|
|
|
3
3
|
const runtime = require('../../dist/runtime')
|
|
4
4
|
const document = runtime.document
|
|
5
5
|
global.document = runtime.document
|
|
6
|
-
|
|
7
|
-
describe('document', () => {
|
|
8
6
|
|
|
7
|
+
describe('document', () => {
|
|
9
8
|
it('document setCookie', async () => {
|
|
10
9
|
expect(document.cookie).toBe('')
|
|
11
10
|
document.cookie = 'aaa=1111-2222-33-444-abcdefgasd; path=/; expires=Mon, 18 Jan 2038 19:14:07 GMT; secure;'
|
|
@@ -15,6 +14,5 @@ describe('DOM', () => {
|
|
|
15
14
|
'aaa=1111-2222-33-444-abcdefgasd; bbb=23123-aswe-4a7a-a740-f55dfd296b1d; ccc=69asd3d81234668942'
|
|
16
15
|
)
|
|
17
16
|
})
|
|
18
|
-
|
|
19
17
|
})
|
|
20
18
|
})
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { window } from '@tarojs/runtime'
|
|
2
|
+
import { request, RequestTask } from '@tarojs/taro'
|
|
3
|
+
|
|
4
|
+
import { XMLHttpRequest, XMLHttpRequestEvent } from '../../dist/runtime'
|
|
5
|
+
|
|
6
|
+
jest.mock('@tarojs/taro', () => {
|
|
7
|
+
return {
|
|
8
|
+
request: jest.fn(),
|
|
9
|
+
}
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const requestMock = jest.mocked(request)
|
|
13
|
+
|
|
14
|
+
describe('XMLHttpRequest', () => {
|
|
15
|
+
it('大写header key', async () => {
|
|
16
|
+
const data = 'success'
|
|
17
|
+
// 模拟实现 request 函数
|
|
18
|
+
requestMock.mockImplementation((opt) => {
|
|
19
|
+
if (opt.success) {
|
|
20
|
+
const header = { 'Content-Length': data.length.toString() }
|
|
21
|
+
opt.success({ data: data as any, header, statusCode: 200, errMsg: '' })
|
|
22
|
+
}
|
|
23
|
+
if (opt.complete) {
|
|
24
|
+
opt.complete({ errMsg: '' })
|
|
25
|
+
}
|
|
26
|
+
return {} as RequestTask<any>
|
|
27
|
+
})
|
|
28
|
+
// 发起请求
|
|
29
|
+
const xhr = new XMLHttpRequest()
|
|
30
|
+
xhr.open('GET', 'localhost')
|
|
31
|
+
const req = new Promise<XMLHttpRequestEvent>((resolve, reject) => {
|
|
32
|
+
xhr.addEventListener('load', resolve)
|
|
33
|
+
xhr.addEventListener('error', reject)
|
|
34
|
+
})
|
|
35
|
+
xhr.send('')
|
|
36
|
+
await req
|
|
37
|
+
// 检查是否能正常读取大写的header
|
|
38
|
+
expect(xhr.status).toBe(200)
|
|
39
|
+
expect(data.length).toBeGreaterThan(0)
|
|
40
|
+
expect(xhr.getResponseHeader('Content-length')).toBe(data.length.toString())
|
|
41
|
+
expect(xhr.getResponseHeader('content-length')).toBe(data.length.toString())
|
|
42
|
+
expect(xhr.getResponseHeader('Content-Length')).toBe(data.length.toString())
|
|
43
|
+
})
|
|
44
|
+
it('小写header key', async () => {
|
|
45
|
+
const data = 'success'
|
|
46
|
+
// 模拟实现 request 函数
|
|
47
|
+
requestMock.mockImplementation((opt) => {
|
|
48
|
+
if (opt.success) {
|
|
49
|
+
const header = { 'content-length': data.length.toString() }
|
|
50
|
+
opt.success({ data: data as any, header, statusCode: 200, errMsg: '' })
|
|
51
|
+
}
|
|
52
|
+
if (opt.complete) {
|
|
53
|
+
opt.complete({ errMsg: '' })
|
|
54
|
+
}
|
|
55
|
+
return {} as RequestTask<any>
|
|
56
|
+
})
|
|
57
|
+
const xhr = new XMLHttpRequest()
|
|
58
|
+
xhr.open('GET', 'localhost')
|
|
59
|
+
const req = new Promise<XMLHttpRequestEvent>((resolve, reject) => {
|
|
60
|
+
xhr.addEventListener('load', resolve)
|
|
61
|
+
xhr.addEventListener('error', reject)
|
|
62
|
+
})
|
|
63
|
+
xhr.send('')
|
|
64
|
+
await req
|
|
65
|
+
// 检查是否能成功读取小写的header
|
|
66
|
+
expect(xhr.status).toBe(200)
|
|
67
|
+
expect(xhr.responseText).toBe(data)
|
|
68
|
+
expect(xhr.getResponseHeader('Content-length')).toBe(data.length.toString())
|
|
69
|
+
expect(xhr.getResponseHeader('content-length')).toBe(data.length.toString())
|
|
70
|
+
expect(xhr.getResponseHeader('Content-Length')).toBe(data.length.toString())
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('set-cookie', async () => {
|
|
74
|
+
const data = 'success'
|
|
75
|
+
// 模拟实现 request 函数
|
|
76
|
+
requestMock.mockImplementation((opt) => {
|
|
77
|
+
if (opt.success) {
|
|
78
|
+
const header = { 'set-cookie': 'aaa=bbb; domain=taro.com' }
|
|
79
|
+
opt.success({ data: data as any, header, statusCode: 200, errMsg: '' })
|
|
80
|
+
}
|
|
81
|
+
if (opt.complete) {
|
|
82
|
+
opt.complete({ errMsg: '' })
|
|
83
|
+
}
|
|
84
|
+
return {} as RequestTask<any>
|
|
85
|
+
})
|
|
86
|
+
// 发送一个请求
|
|
87
|
+
const xhr = new XMLHttpRequest()
|
|
88
|
+
xhr.open('GET', 'localhost')
|
|
89
|
+
const req = new Promise<XMLHttpRequestEvent>((resolve, reject) => {
|
|
90
|
+
xhr.addEventListener('load', resolve)
|
|
91
|
+
xhr.addEventListener('error', reject)
|
|
92
|
+
})
|
|
93
|
+
// 在发送请求之前cookie为空
|
|
94
|
+
expect(window.document.cookie.length).toBe(0)
|
|
95
|
+
xhr.send('')
|
|
96
|
+
// 等待请求加载完成
|
|
97
|
+
await req
|
|
98
|
+
// 检查是否能读取set-cookie
|
|
99
|
+
expect(window.document.cookie.length).not.toBe(0)
|
|
100
|
+
})
|
|
101
|
+
})
|
package/src/runtime/Cookie.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
Copyright (c) 2019 wechat-miniprogram.
|
|
2
|
+
Copyright (c) 2019 wechat-miniprogram.
|
|
3
3
|
Reference and modify code by miniprogram-render/src/bom/cookie.js.
|
|
4
4
|
|
|
5
5
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
@@ -63,27 +63,27 @@ function createXMLHttpRequestEvent (event: string, target:XMLHttpRequest, loaded
|
|
|
63
63
|
const e = createEvent(event) as XMLHttpRequestEvent
|
|
64
64
|
try {
|
|
65
65
|
Object.defineProperties(e, {
|
|
66
|
-
|
|
66
|
+
currentTarget: {
|
|
67
67
|
enumerable: true,
|
|
68
68
|
value: target
|
|
69
69
|
},
|
|
70
|
-
|
|
70
|
+
target: {
|
|
71
71
|
enumerable: true,
|
|
72
72
|
value: target
|
|
73
73
|
},
|
|
74
|
-
|
|
74
|
+
loaded: {
|
|
75
75
|
enumerable: true,
|
|
76
76
|
value: loaded || 0
|
|
77
77
|
},
|
|
78
78
|
// 读 Content-Range 字段,目前来说作用不大,先和 loaded 保持一致
|
|
79
|
-
|
|
79
|
+
total: {
|
|
80
80
|
enumerable: true,
|
|
81
81
|
value: loaded || 0
|
|
82
82
|
}
|
|
83
83
|
})
|
|
84
84
|
} catch (err) {
|
|
85
85
|
// no handler
|
|
86
|
-
}
|
|
86
|
+
}
|
|
87
87
|
return e
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -118,7 +118,10 @@ export class XMLHttpRequest extends Events {
|
|
|
118
118
|
#withCredentials: boolean
|
|
119
119
|
#requestTask: null | Taro.RequestTask<any>
|
|
120
120
|
|
|
121
|
-
//
|
|
121
|
+
// 事件正常流转: loadstart => progress(可能多次) => load => loadend
|
|
122
|
+
// error 流转: loadstart => error => loadend
|
|
123
|
+
// abort 流转: loadstart => abort => loadend
|
|
124
|
+
// web在线测试: https://developer.mozilla.org/zh-CN/play
|
|
122
125
|
|
|
123
126
|
/** 当 request 被停止时触发,例如当程序调用 XMLHttpRequest.abort() 时 */
|
|
124
127
|
onabort: ((e: XMLHttpRequestEvent) => void) | null = null
|
|
@@ -223,6 +226,7 @@ export class XMLHttpRequest extends Events {
|
|
|
223
226
|
// 头信息
|
|
224
227
|
const header = Object.assign({}, this.#header)
|
|
225
228
|
// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies
|
|
229
|
+
// @ts-ignore
|
|
226
230
|
header.cookie = window.document.$$cookie
|
|
227
231
|
if (!this.withCredentials) {
|
|
228
232
|
// 不同源,要求 withCredentials 为 true 才携带 cookie
|
|
@@ -259,7 +263,7 @@ export class XMLHttpRequest extends Events {
|
|
|
259
263
|
|
|
260
264
|
if (ENABLE_COOKIE) {
|
|
261
265
|
// 处理 set-cookie
|
|
262
|
-
const setCookieStr =
|
|
266
|
+
const setCookieStr = this.getResponseHeader('set-cookie')
|
|
263
267
|
|
|
264
268
|
if (setCookieStr && typeof setCookieStr === 'string') {
|
|
265
269
|
let start = 0
|
|
@@ -294,12 +298,13 @@ export class XMLHttpRequest extends Events {
|
|
|
294
298
|
// 处理返回数据
|
|
295
299
|
if (data) {
|
|
296
300
|
this.#callReadyStateChange(XMLHttpRequest.LOADING)
|
|
297
|
-
const
|
|
301
|
+
const contentLength = Number(this.getResponseHeader('content-length') || 0)
|
|
302
|
+
const loadstartEvent = createXMLHttpRequestEvent('loadstart', this, contentLength)
|
|
298
303
|
this.trigger('loadstart', loadstartEvent)
|
|
299
304
|
isFunction(this.onloadstart) && this.onloadstart(loadstartEvent)
|
|
300
305
|
this.#response = data
|
|
301
306
|
|
|
302
|
-
const loadEvent = createXMLHttpRequestEvent('load', this,
|
|
307
|
+
const loadEvent = createXMLHttpRequestEvent('load', this, contentLength)
|
|
303
308
|
this.trigger('load', loadEvent)
|
|
304
309
|
isFunction(this.onload) && this.onload(loadEvent)
|
|
305
310
|
}
|
|
@@ -309,8 +314,30 @@ export class XMLHttpRequest extends Events {
|
|
|
309
314
|
* 请求失败
|
|
310
315
|
*/
|
|
311
316
|
#requestFail (err) {
|
|
317
|
+
// 微信小程序,无论接口返回200还是其他,响应无论是否有错误,都会进入 success 回调;只有类似超时这种请求错误才会进入 fail 回调
|
|
318
|
+
//
|
|
319
|
+
/**
|
|
320
|
+
* 阿里系小程序,接口返回非200状态码,会进入 fail 回调, 此时 err 对象结构如下(当错误码为 14 或 19 时,会多返回 status、data、headers。可通过这些字段获取服务端相关错误信息):
|
|
321
|
+
{
|
|
322
|
+
data: "{\"code\": 401,\"msg\":\"登录过期,请重新登录\"}"
|
|
323
|
+
error: 19
|
|
324
|
+
errorMessage: "http status error"
|
|
325
|
+
headers: {date: 'Mon, 14 Aug 2023 08:54:58 GMT', content-type: 'application/json;charset=UTF-8', content-length: '52', connection: 'close', access-control-allow-credentials: 'true', …}
|
|
326
|
+
originalData: "{\"code\": 401,\"msg\":\"登录过期,请重新登录\"}"
|
|
327
|
+
status: 401
|
|
328
|
+
}
|
|
329
|
+
*/
|
|
330
|
+
// 统一行为,能正常响应的,都算 success.
|
|
331
|
+
if (err.status) {
|
|
332
|
+
this.#requestSuccess({
|
|
333
|
+
data: err,
|
|
334
|
+
statusCode: err.status,
|
|
335
|
+
header: err.headers
|
|
336
|
+
})
|
|
337
|
+
return
|
|
338
|
+
}
|
|
312
339
|
this.#status = 0
|
|
313
|
-
this.#statusText = err.errMsg
|
|
340
|
+
this.#statusText = err.errMsg || err.errorMessage
|
|
314
341
|
const errorEvent = createXMLHttpRequestEvent('error', this, 0)
|
|
315
342
|
this.trigger('error', errorEvent)
|
|
316
343
|
isFunction(this.onerror) && this.onerror(errorEvent)
|
|
@@ -324,7 +351,8 @@ export class XMLHttpRequest extends Events {
|
|
|
324
351
|
this.#callReadyStateChange(XMLHttpRequest.DONE)
|
|
325
352
|
|
|
326
353
|
if (this.#status) {
|
|
327
|
-
const
|
|
354
|
+
const contentLength = Number(this.getResponseHeader('content-length') || 0)
|
|
355
|
+
const loadendEvent = createXMLHttpRequestEvent('loadend', this, contentLength)
|
|
328
356
|
this.trigger('loadend', loadendEvent)
|
|
329
357
|
isFunction(this.onloadend) && this.onloadend(loadendEvent)
|
|
330
358
|
}
|
|
@@ -397,8 +425,7 @@ export class XMLHttpRequest extends Events {
|
|
|
397
425
|
}
|
|
398
426
|
|
|
399
427
|
getAllResponseHeaders () {
|
|
400
|
-
if (this.#readyState === XMLHttpRequest.UNSENT || this.#readyState === XMLHttpRequest.OPENED || !this.#resHeader)
|
|
401
|
-
return ''
|
|
428
|
+
if (this.#readyState === XMLHttpRequest.UNSENT || this.#readyState === XMLHttpRequest.OPENED || !this.#resHeader) { return '' }
|
|
402
429
|
|
|
403
430
|
return Object.keys(this.#resHeader)
|
|
404
431
|
.map((key) => `${key}: ${this.#resHeader![key]}`)
|
|
@@ -406,8 +433,7 @@ export class XMLHttpRequest extends Events {
|
|
|
406
433
|
}
|
|
407
434
|
|
|
408
435
|
getResponseHeader (name) {
|
|
409
|
-
if (this.#readyState === XMLHttpRequest.UNSENT || this.#readyState === XMLHttpRequest.OPENED || !this.#resHeader)
|
|
410
|
-
return null
|
|
436
|
+
if (this.#readyState === XMLHttpRequest.UNSENT || this.#readyState === XMLHttpRequest.OPENED || !this.#resHeader) { return null }
|
|
411
437
|
|
|
412
438
|
// 处理大小写不敏感
|
|
413
439
|
const key = Object.keys(this.#resHeader).find((item) => item.toLowerCase() === name.toLowerCase())
|
package/src/runtime/index.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { document, window } from '@tarojs/runtime'
|
|
2
|
-
import { isWebPlatform } from '@tarojs/shared'
|
|
3
2
|
|
|
4
3
|
import { Cookie, createCookieInstance } from './Cookie'
|
|
5
4
|
import { type XMLHttpRequestEvent, XMLHttpRequest } from './XMLHttpRequest'
|
|
6
5
|
|
|
7
6
|
declare const ENABLE_COOKIE: boolean
|
|
8
7
|
|
|
9
|
-
if (
|
|
8
|
+
if (process.env.TARO_PLATFORM !== 'web') {
|
|
10
9
|
if (ENABLE_COOKIE) {
|
|
11
10
|
const _cookie = createCookieInstance()
|
|
12
|
-
|
|
11
|
+
|
|
13
12
|
Object.defineProperties(document, {
|
|
14
13
|
URL: {
|
|
15
14
|
get () {
|