@tarojs/plugin-http 3.6.0-beta.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.
- package/LICENSE +21 -0
- package/README.MD +59 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +45 -0
- package/dist/runtime.d.ts +94 -0
- package/dist/runtime.js +654 -0
- package/index.js +3 -0
- package/package.json +42 -0
- package/src/__tests__/cookie.spec.js +89 -0
- package/src/__tests__/dom.spec.js +20 -0
- package/src/__tests__/setup.js +1 -0
- package/src/__tests__/utils.js +8 -0
- package/src/index.ts +52 -0
- package/src/runtime/Cookie.ts +312 -0
- package/src/runtime/XMLHttpRequest.ts +398 -0
- package/src/runtime/index.ts +35 -0
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tarojs/plugin-http",
|
|
3
|
+
"version": "3.6.0-beta.2",
|
|
4
|
+
"description": "Taro 小程序端支持使用 web 请求 的插件",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"src",
|
|
8
|
+
"dist",
|
|
9
|
+
"index.js",
|
|
10
|
+
"package.json"
|
|
11
|
+
],
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/NervJS/taro.git"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"Taro"
|
|
18
|
+
],
|
|
19
|
+
"author": "bigmeow <https://github.com/bigmeow>",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/NervJS/taro/issues"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/NervJS/taro#readme",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@tarojs/runtime": "3.6.0-beta.2",
|
|
27
|
+
"@tarojs/service": "3.6.0-beta.2",
|
|
28
|
+
"@tarojs/shared": "3.6.0-beta.2"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@rollup/plugin-json": "^4.1.0",
|
|
32
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
33
|
+
"rollup": "^3.8.1",
|
|
34
|
+
"tslib": "^2.4.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"dev": "rollup -c -w --bundleConfigAsCjs",
|
|
38
|
+
"build": "rollup -c --bundleConfigAsCjs",
|
|
39
|
+
"test": "jest",
|
|
40
|
+
"test:ci": "jest --ci -i --coverage false"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const { delay } = require('./utils')
|
|
2
|
+
|
|
3
|
+
describe('cookie', () => {
|
|
4
|
+
const runtime = require('../../dist/runtime')
|
|
5
|
+
|
|
6
|
+
const cookie = new runtime.Cookie()
|
|
7
|
+
const url1 = 'http://sub.taro.com/p/a/t/h?query=string#hash'
|
|
8
|
+
const url2 = 'http://xxx.sub.taro.com/p/a/t/h?query=string#hash'
|
|
9
|
+
const url3 = 'http://sub2.taro.com/p/a/t/h?query=string#hash'
|
|
10
|
+
const url4 = 'https://sub.taro.com/p/a/t/h?query=string#hash'
|
|
11
|
+
|
|
12
|
+
it('key-value', () => {
|
|
13
|
+
cookie.setCookie('aaa=bbb', url1)
|
|
14
|
+
expect(cookie.getCookie(url1)).toBe('aaa=bbb')
|
|
15
|
+
cookie.setCookie('ccc=ddd\nasdf', url1)
|
|
16
|
+
cookie.setCookie('eee=fff;asdf', url1)
|
|
17
|
+
cookie.setCookie('ggg=;asdf', url1)
|
|
18
|
+
cookie.setCookie('hhh\n=;asdf', url1)
|
|
19
|
+
expect(cookie.getCookie(url1)).toBe('aaa=bbb; ccc=ddd; eee=fff; ggg=')
|
|
20
|
+
cookie.setCookie('aaa=abc', url1)
|
|
21
|
+
cookie.setCookie('ccc=cba\nasdf', url1)
|
|
22
|
+
expect(cookie.getCookie(url1)).toBe('aaa=abc; ccc=cba; eee=fff; ggg=')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('maxAge', async () => {
|
|
26
|
+
cookie.setCookie('aaa=bbb; max-age=1', url1)
|
|
27
|
+
await delay(1001)
|
|
28
|
+
expect(cookie.getCookie(url1)).toBe('ccc=cba; eee=fff; ggg=')
|
|
29
|
+
cookie.setCookie('ccc=ddd; max-age=-10', url1)
|
|
30
|
+
expect(cookie.getCookie(url1)).toBe('eee=fff; ggg=')
|
|
31
|
+
cookie.setCookie('eee=fff; max-age=', url1)
|
|
32
|
+
expect(cookie.getCookie(url1)).toBe('eee=fff; ggg=')
|
|
33
|
+
cookie.setCookie('eee=fff; max-age=abc', url1)
|
|
34
|
+
expect(cookie.getCookie(url1)).toBe('eee=fff; ggg=')
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('expires', async () => {
|
|
38
|
+
cookie.setCookie(`eee=fff; expires=${new Date(Date.now()).toUTCString()}`, url1)
|
|
39
|
+
expect(cookie.getCookie(url1)).toBe('ggg=')
|
|
40
|
+
cookie.setCookie(`ggg=fff; expires=${new Date(Date.now() + 1000).toUTCString()}`, url1)
|
|
41
|
+
expect(cookie.getCookie(url1)).toBe('ggg=fff')
|
|
42
|
+
await delay(1001)
|
|
43
|
+
expect(cookie.getCookie(url1)).toBe('')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('max-age 优先于 expires', async () => {
|
|
47
|
+
cookie.setCookie(`aaa=bbb; max-age=1000; expires=${new Date(Date.now()).toUTCString()}`, url1)
|
|
48
|
+
expect(cookie.getCookie(url1)).toBe('aaa=bbb')
|
|
49
|
+
cookie.setCookie(`aaa=bbb; max-age=0; expires=${new Date(Date.now() + 1000 * 1000).toUTCString()}`, url1)
|
|
50
|
+
expect(cookie.getCookie(url1)).toBe('')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('domain', async () => {
|
|
54
|
+
cookie.setCookie('aaa=bbb; domain=taro.com', url1)
|
|
55
|
+
cookie.setCookie('abc=cba; domain=sub.taro.com', url1)
|
|
56
|
+
expect(cookie.getCookie(url1)).toBe('aaa=bbb; abc=cba')
|
|
57
|
+
cookie.setCookie('ccc=ddd; domain=xxx.sub.taro.com', url1) // 不符合 domain,不写入 cookie
|
|
58
|
+
expect(cookie.getCookie(url1)).toBe('aaa=bbb; abc=cba')
|
|
59
|
+
cookie.setCookie('eee=fff; domain=xxx.sub.taro.com', url2)
|
|
60
|
+
cookie.setCookie('ggg=; domain=sub2.taro.com', url3)
|
|
61
|
+
expect(cookie.getCookie(url1)).toBe('aaa=bbb; abc=cba')
|
|
62
|
+
expect(cookie.getCookie(url2)).toBe('aaa=bbb; abc=cba; eee=fff')
|
|
63
|
+
expect(cookie.getCookie(url3)).toBe('aaa=bbb; ggg=')
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('path', async () => {
|
|
67
|
+
cookie.setCookie('eee=fff; path=/p/a/t/x', url1)
|
|
68
|
+
expect(cookie.getCookie(url1)).toBe('aaa=bbb; abc=cba')
|
|
69
|
+
cookie.setCookie('ggg=hhh; path=/p/a/t', url1)
|
|
70
|
+
expect(cookie.getCookie(url1)).toBe('aaa=bbb; abc=cba; ggg=hhh')
|
|
71
|
+
cookie.setCookie('iii=jjj; path=/p/a/x', url1)
|
|
72
|
+
expect(cookie.getCookie(url1)).toBe('aaa=bbb; abc=cba; ggg=hhh')
|
|
73
|
+
cookie.setCookie('kkk=lll; path=/p/a', url1)
|
|
74
|
+
expect(cookie.getCookie(url1)).toBe('aaa=bbb; abc=cba; ggg=hhh; kkk=lll')
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('secure', async () => {
|
|
78
|
+
cookie.setCookie('mmm=nnn; secure', url1)
|
|
79
|
+
expect(cookie.getCookie(url1)).toBe('aaa=bbb; abc=cba; ggg=hhh; kkk=lll')
|
|
80
|
+
expect(cookie.getCookie(url4)).toBe('aaa=bbb; abc=cba; ggg=hhh; kkk=lll; mmm=nnn')
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('httpOnly', async () => {
|
|
84
|
+
cookie.setCookie('ooo=ppp; httpOnly', url1)
|
|
85
|
+
expect(cookie.getCookie(url1)).toBe('aaa=bbb; abc=cba; ggg=hhh; kkk=lll; ooo=ppp')
|
|
86
|
+
expect(cookie.getCookie(url4)).toBe('aaa=bbb; abc=cba; ggg=hhh; kkk=lll; mmm=nnn')
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
describe('DOM', () => {
|
|
2
|
+
process.env.FRAMEWORK = 'nerv'
|
|
3
|
+
const runtime = require('../../dist/runtime')
|
|
4
|
+
const document = runtime.document
|
|
5
|
+
global.document = runtime.document
|
|
6
|
+
|
|
7
|
+
describe('document', () => {
|
|
8
|
+
|
|
9
|
+
it('document setCookie', async () => {
|
|
10
|
+
expect(document.cookie).toBe('')
|
|
11
|
+
document.cookie = 'aaa=1111-2222-33-444-abcdefgasd; path=/; expires=Mon, 18 Jan 2038 19:14:07 GMT; secure;'
|
|
12
|
+
document.cookie = 'bbb=23123-aswe-4a7a-a740-f55dfd296b1d; path=/; expires=Mon, 18 Jan 2038 19:14:07 GMT'
|
|
13
|
+
document.cookie = 'ccc=69asd3d81234668942; path=/; expires=Mon, 18 Jan 2038 19:14:07 GMT'
|
|
14
|
+
expect(document.cookie).toBe(
|
|
15
|
+
'aaa=1111-2222-33-444-abcdefgasd; bbb=23123-aswe-4a7a-a740-f55dfd296b1d; ccc=69asd3d81234668942'
|
|
16
|
+
)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
})
|
|
20
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
process.env.TARO_ENV = 'weapp'
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { isArray, isString } from '@tarojs/shared'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
4
|
+
import { name as packageName } from '../package.json'
|
|
5
|
+
|
|
6
|
+
import type { IPluginContext, TaroPlatformBase } from '@tarojs/service'
|
|
7
|
+
|
|
8
|
+
interface IOptions {
|
|
9
|
+
/** 支持 document.cookie 和 http 设置 cookie (默认false) */
|
|
10
|
+
enableCookie?: boolean
|
|
11
|
+
/** 禁用掉 FormData 全局对象 (默认true禁用) */
|
|
12
|
+
disabledFormData?: boolean
|
|
13
|
+
/** 禁用掉 Blob 全局对象 (默认true禁用) */
|
|
14
|
+
disabledBlob?: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default (ctx: IPluginContext, options: IOptions) => {
|
|
18
|
+
if (!['h5', 'rn'].includes(ctx.runOpts.options.platform)) {
|
|
19
|
+
ctx.modifyWebpackChain(({ chain }) => {
|
|
20
|
+
chain.plugin('definePlugin').tap((args) => {
|
|
21
|
+
args[0].ENABLE_COOKIE = options.enableCookie ?? false
|
|
22
|
+
return args
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const runtimeAlia = `${packageName}/dist/runtime`
|
|
26
|
+
chain.resolve.alias.set(runtimeAlia, path.join(__dirname, 'runtime.js'))
|
|
27
|
+
// 注入相关全局BOM对象
|
|
28
|
+
chain.plugin('providerPlugin').tap((args) => {
|
|
29
|
+
args[0].XMLHttpRequest = [runtimeAlia, 'XMLHttpRequest']
|
|
30
|
+
|
|
31
|
+
// 实际上本runtime 没有实现 FormData 和 Blob 对象, 所以第三方库中的这2个对象会被替换成 undefined
|
|
32
|
+
// (axios这类请求库用到了这2个对象,所以要么实现它要么把它替换掉, 这里我们选择把它替换掉,这样可以确保除了上传以外的功能可以继续使用)
|
|
33
|
+
;(options.disabledFormData ?? true) && (args[0].FormData ||= [runtimeAlia, 'FormData'])
|
|
34
|
+
;(options.disabledBlob ?? true) && (args[0].Blob ||= [runtimeAlia, 'Blob'])
|
|
35
|
+
|
|
36
|
+
return args
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
ctx.registerMethod({
|
|
41
|
+
name: 'onSetupClose',
|
|
42
|
+
fn (platform: TaroPlatformBase) {
|
|
43
|
+
const injectedPath = `post:${packageName}/dist/runtime`
|
|
44
|
+
if (isArray(platform.runtimePath)) {
|
|
45
|
+
platform.runtimePath.push(injectedPath)
|
|
46
|
+
} else if (isString(platform.runtimePath)) {
|
|
47
|
+
platform.runtimePath = [platform.runtimePath, injectedPath]
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
Copyright (c) 2019 wechat-miniprogram.
|
|
3
|
+
Reference and modify code by miniprogram-render/src/bom/cookie.js.
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted.
|
|
7
|
+
|
|
8
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
9
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
10
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
11
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
12
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
13
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
14
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
15
|
+
***************************************************************************** */
|
|
16
|
+
import { parseUrl } from '@tarojs/runtime'
|
|
17
|
+
import { getStorageSync, setStorage } from '@tarojs/taro'
|
|
18
|
+
|
|
19
|
+
const STORAGE_KEY = 'PAGE_COOKIE'
|
|
20
|
+
export class Cookie {
|
|
21
|
+
#map: any
|
|
22
|
+
constructor () {
|
|
23
|
+
this.#map = {} // 三维数组,domain - path - key
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static parse (cookieStr: string) {
|
|
27
|
+
if (!cookieStr && typeof cookieStr !== 'string') return null
|
|
28
|
+
|
|
29
|
+
const cookieStrArr = cookieStr.trim().split(';')
|
|
30
|
+
|
|
31
|
+
// key-value
|
|
32
|
+
// eslint-disable-next-line no-control-regex
|
|
33
|
+
const parseKeyValue = /^([^=;\x00-\x1F]+)=([^;\n\r\0\x00-\x1F]*).*/.exec(cookieStrArr.shift()!)
|
|
34
|
+
if (!parseKeyValue) return null
|
|
35
|
+
|
|
36
|
+
const key = (parseKeyValue[1] || '').trim()
|
|
37
|
+
const value = (parseKeyValue[2] || '').trim()
|
|
38
|
+
|
|
39
|
+
// 其他字段
|
|
40
|
+
let path: string | null = null
|
|
41
|
+
let domain: string | null = null
|
|
42
|
+
let expires: number | null = null
|
|
43
|
+
let maxAge: number | null = null
|
|
44
|
+
let secure = false
|
|
45
|
+
let httpOnly = false
|
|
46
|
+
|
|
47
|
+
for (let item of cookieStrArr) {
|
|
48
|
+
item = item.trim()
|
|
49
|
+
if (!item) continue
|
|
50
|
+
|
|
51
|
+
let [key, value] = item.split('=')
|
|
52
|
+
key = (key || '').trim().toLowerCase()
|
|
53
|
+
value = (value || '').trim()
|
|
54
|
+
|
|
55
|
+
if (!key) continue
|
|
56
|
+
|
|
57
|
+
switch (key) {
|
|
58
|
+
case 'path':
|
|
59
|
+
if (value[0] === '/') path = value
|
|
60
|
+
break
|
|
61
|
+
case 'domain':
|
|
62
|
+
value = value.replace(/^\./, '').toLowerCase()
|
|
63
|
+
if (value) domain = value
|
|
64
|
+
break
|
|
65
|
+
case 'expires':
|
|
66
|
+
if (value) {
|
|
67
|
+
const timeStamp = Date.parse(value)
|
|
68
|
+
if (timeStamp) expires = timeStamp
|
|
69
|
+
}
|
|
70
|
+
break
|
|
71
|
+
case 'max-age':
|
|
72
|
+
if (/^-?[0-9]+$/.test(value)) maxAge = +value * 1000
|
|
73
|
+
break
|
|
74
|
+
case 'secure':
|
|
75
|
+
secure = true
|
|
76
|
+
break
|
|
77
|
+
case 'httponly':
|
|
78
|
+
httpOnly = true
|
|
79
|
+
break
|
|
80
|
+
default:
|
|
81
|
+
// ignore
|
|
82
|
+
break
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
key,
|
|
88
|
+
value,
|
|
89
|
+
path,
|
|
90
|
+
domain,
|
|
91
|
+
expires,
|
|
92
|
+
maxAge,
|
|
93
|
+
secure,
|
|
94
|
+
httpOnly,
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 判断 domain
|
|
100
|
+
*/
|
|
101
|
+
$_checkDomain (host, cookieDomain) {
|
|
102
|
+
if (host === cookieDomain) return true
|
|
103
|
+
|
|
104
|
+
const index = host.indexOf(`.${cookieDomain}`)
|
|
105
|
+
|
|
106
|
+
return index > 0 && cookieDomain.length + index + 1 === host.length
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 判断 path
|
|
111
|
+
*/
|
|
112
|
+
$_checkPath (path, cookiePath) {
|
|
113
|
+
if (path === cookiePath) return true
|
|
114
|
+
|
|
115
|
+
cookiePath = cookiePath === '/' ? '' : cookiePath
|
|
116
|
+
return path.indexOf(`${cookiePath}/`) === 0
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 判断过期
|
|
121
|
+
*/
|
|
122
|
+
$_checkExpires (cookie) {
|
|
123
|
+
const now = Date.now()
|
|
124
|
+
|
|
125
|
+
// maxAge 优先
|
|
126
|
+
if (cookie.maxAge !== null) return cookie.createTime + cookie.maxAge > now
|
|
127
|
+
|
|
128
|
+
// 判断 expires
|
|
129
|
+
if (cookie.expires !== null) return cookie.expires > now
|
|
130
|
+
|
|
131
|
+
return true
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 设置 cookie
|
|
136
|
+
*/
|
|
137
|
+
setCookie (cookie, url) {
|
|
138
|
+
cookie = Cookie.parse(cookie)
|
|
139
|
+
|
|
140
|
+
if (!cookie) return
|
|
141
|
+
|
|
142
|
+
const { hostname, port, pathname } = parseUrl(url)
|
|
143
|
+
const host = (hostname || '') + (port ? ':' + port : '') || ''
|
|
144
|
+
const path = (pathname || '')[0] === '/' ? pathname : '/'
|
|
145
|
+
|
|
146
|
+
if (cookie.domain) {
|
|
147
|
+
// 判断 domain
|
|
148
|
+
if (!this.$_checkDomain(host, cookie.domain)) return
|
|
149
|
+
} else {
|
|
150
|
+
// 使用 host 作为默认的 domain
|
|
151
|
+
cookie.domain = host
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 需要设置 path 字段的情况,取 url 中除去最后一节的 path
|
|
155
|
+
if (!cookie.path || cookie.path[0] !== '/') {
|
|
156
|
+
const lastIndex = path.lastIndexOf('/')
|
|
157
|
+
|
|
158
|
+
cookie.path = lastIndex === 0 ? path : path.substr(0, lastIndex)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// 存入 cookie
|
|
162
|
+
const map = this.#map
|
|
163
|
+
const cookieDomain = cookie.domain
|
|
164
|
+
const cookiePath = cookie.path
|
|
165
|
+
const cookieKey = cookie.key
|
|
166
|
+
|
|
167
|
+
if (!map[cookieDomain]) map[cookieDomain] = {}
|
|
168
|
+
if (!map[cookieDomain][cookiePath]) map[cookieDomain][cookiePath] = {}
|
|
169
|
+
|
|
170
|
+
const oldCookie = map[cookieDomain][cookiePath][cookieKey]
|
|
171
|
+
cookie.createTime = (oldCookie && oldCookie.createTime) || Date.now()
|
|
172
|
+
|
|
173
|
+
if (this.$_checkExpires(cookie)) {
|
|
174
|
+
// 未过期
|
|
175
|
+
map[cookieDomain][cookiePath][cookieKey] = cookie
|
|
176
|
+
} else if (oldCookie) {
|
|
177
|
+
// 存在旧 cookie,且被设置为已过期
|
|
178
|
+
delete map[cookieDomain][cookiePath][cookieKey]
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 持久化 cookie
|
|
182
|
+
setStorage &&
|
|
183
|
+
setStorage({
|
|
184
|
+
key: STORAGE_KEY,
|
|
185
|
+
data: this.serialize(),
|
|
186
|
+
})
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* 拉取 cookie
|
|
191
|
+
*/
|
|
192
|
+
getCookie (url: string, includeHttpOnly = false) {
|
|
193
|
+
const { protocol, hostname, port, pathname } = parseUrl(url)
|
|
194
|
+
const host = (hostname || '') + (port ? ':' + port : '') || ''
|
|
195
|
+
const path = (pathname || '')[0] === '/' ? pathname : '/'
|
|
196
|
+
const res: any[] = []
|
|
197
|
+
|
|
198
|
+
const map = this.#map
|
|
199
|
+
const domainList = Object.keys(map)
|
|
200
|
+
|
|
201
|
+
for (const domainItem of domainList) {
|
|
202
|
+
// 判断 domain
|
|
203
|
+
if (this.$_checkDomain(host, domainItem)) {
|
|
204
|
+
const domainMap = map[domainItem] || {}
|
|
205
|
+
const pathList = Object.keys(domainMap)
|
|
206
|
+
|
|
207
|
+
for (const pathItem of pathList) {
|
|
208
|
+
// 判断 path
|
|
209
|
+
if (this.$_checkPath(path, pathItem)) {
|
|
210
|
+
const pathMap = map[domainItem][pathItem] || {}
|
|
211
|
+
|
|
212
|
+
Object.keys(pathMap).forEach((key) => {
|
|
213
|
+
const cookie: any = pathMap[key]
|
|
214
|
+
|
|
215
|
+
if (!cookie) return
|
|
216
|
+
|
|
217
|
+
// 判断协议
|
|
218
|
+
if (cookie.secure && protocol !== 'https:' && protocol !== 'wss:') return
|
|
219
|
+
if (!includeHttpOnly && cookie.httpOnly && protocol && protocol !== 'http:') return
|
|
220
|
+
|
|
221
|
+
// 判断过期
|
|
222
|
+
if (this.$_checkExpires(cookie)) {
|
|
223
|
+
res.push(cookie)
|
|
224
|
+
} else {
|
|
225
|
+
// 过期,删掉
|
|
226
|
+
delete map[domainItem][pathItem][key]
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return res
|
|
235
|
+
.sort((a, b) => {
|
|
236
|
+
const gap = a.createTime - b.createTime
|
|
237
|
+
|
|
238
|
+
if (!gap) {
|
|
239
|
+
return a.key < b.key ? -1 : 1
|
|
240
|
+
} else {
|
|
241
|
+
return gap
|
|
242
|
+
}
|
|
243
|
+
})
|
|
244
|
+
.map((cookie) => `${cookie.key}=${cookie.value}`)
|
|
245
|
+
.join('; ')
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* 序列化
|
|
250
|
+
*/
|
|
251
|
+
serialize () {
|
|
252
|
+
try {
|
|
253
|
+
return JSON.stringify(this.#map)
|
|
254
|
+
} catch (err) {
|
|
255
|
+
// eslint-disable-next-line no-console
|
|
256
|
+
console.log('cannot serialize the cookie')
|
|
257
|
+
return ''
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* 反序列化
|
|
263
|
+
*/
|
|
264
|
+
deserialize (str) {
|
|
265
|
+
let map = {}
|
|
266
|
+
try {
|
|
267
|
+
map = JSON.parse(str)
|
|
268
|
+
} catch (err) {
|
|
269
|
+
// eslint-disable-next-line no-console
|
|
270
|
+
console.log('cannot deserialize the cookie')
|
|
271
|
+
map = {}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// 合并 cookie
|
|
275
|
+
const domainList = Object.keys(map)
|
|
276
|
+
|
|
277
|
+
for (const domainItem of domainList) {
|
|
278
|
+
const domainMap = map[domainItem] || {}
|
|
279
|
+
const pathList = Object.keys(domainMap)
|
|
280
|
+
|
|
281
|
+
for (const pathItem of pathList) {
|
|
282
|
+
const pathMap = map[domainItem][pathItem] || {}
|
|
283
|
+
|
|
284
|
+
Object.keys(pathMap).forEach((key) => {
|
|
285
|
+
const cookie = pathMap[key]
|
|
286
|
+
|
|
287
|
+
if (!cookie) return
|
|
288
|
+
|
|
289
|
+
// 已存在则不覆盖
|
|
290
|
+
if (!this.#map[domainItem]) this.#map[domainItem] = {}
|
|
291
|
+
if (!this.#map[domainItem][pathItem]) this.#map[domainItem][pathItem] = {}
|
|
292
|
+
if (!this.#map[domainItem][pathItem][key]) this.#map[domainItem][pathItem][key] = cookie
|
|
293
|
+
})
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* 创建 cookie 实例并反序列化
|
|
301
|
+
* @returns
|
|
302
|
+
*/
|
|
303
|
+
export function createCookieInstance () {
|
|
304
|
+
const cookieInstance = new Cookie()
|
|
305
|
+
try {
|
|
306
|
+
const cookie = getStorageSync(STORAGE_KEY)
|
|
307
|
+
if (cookie) cookieInstance.deserialize(cookie)
|
|
308
|
+
} catch (err) {
|
|
309
|
+
// ignore
|
|
310
|
+
}
|
|
311
|
+
return cookieInstance
|
|
312
|
+
}
|